15 届蓝桥杯 14 天省赛冲刺营 1 期 - N皇后问题 - 蓝桥云课 (lanqiao.cn)
#include <bits/stdc++.h>
using namespace std;
#define cx first
#define cy second
const int N=20;
typedef pair<int,int> PII;
int vis[N][N]={0};//注意要设置成int型 因为一个点可能被多个皇后都占领
int cnt=0;
int n;
bool k[N][N];
void func(int x,int y,int w){
for(int i=1;i<=n;i++){
if(i!=x)vis[i][y]+=w;
}
for(int i=1;i<=n;i++){
if(i!=y)vis[x][i]+=w;
}
int su=x+y;
int du=x-y;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i-j==du||(i+j)==su)vis[i][j]+=w;
}
}
}
//主对角线横纵坐标差相同 副对角线横纵坐标和相同
//注意差不要加绝对值 因为(1,3)和(3,1)都是2但是只有一个是主对角线元素
//注意这一题如何回溯的 是通过一个w变量
//注意一次加的时候不要重复
void dfs(int dep){
if(dep==n+1){
for(int i=1;i<=n;i++){
if(k[n][i]){
cnt++;
}
}
return ;
}
for(int i=1;i<=n;i++){
if(vis[dep][i])continue;
// vis[dep][i]++;
k[dep][i]=1;
func(dep,i,1);
dfs(dep+1);
k[dep][i]=0;
// vis[dep][i]--;
func(dep,i,-1);
}
}
void solve(){
cin>>n;
//对于每一行我们选择放哪个位置
dfs(1);//搜第一行
cout<<cnt;
}
int main(){
int t=1;
while(t--)solve();
return 0;
}
15 届蓝桥杯 14 天省赛冲刺营 1 期 - N皇后问题 - 蓝桥云课 (lanqiao.cn)
#include <iostream>
#include <vector>
using namespace std;
int n;
int arr[25][25] = {};
int v[25][25] = {};
int jump[4][2] = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}};
int west[25], west_tr[25];
int north[25], north_tr[25];
vector<int> p;
bool flag = false;
bool check() {
for (int i = 1; i <= n; ++i) {//减到最后肯定都等于0了才行
if (west[i] != west_tr[i] || north[i] != north_tr[i]) return false;
}
return true;
}
void dfs(int x, int y) {
if (flag) return;
if (x == n && y == n) {
if (check()) {//一个答案
for (int i = 0; i < p.size(); ++i) cout << p[i] << " ";
flag = true;
}
return;
}
for (int i = 0; i < 4; ++i) {
int tx = x + jump[i][0];
int ty = y + jump[i][1];
if (tx <= 0 || ty <= 0 || tx > n || ty > n) continue;
if (!v[tx][ty]) {
if(west[tx] >= west_tr[tx] || north[ty] >= north_tr[ty]) continue;
v[tx][ty] = 1;
west[tx]++;
north[ty]++;
p.push_back(arr[tx][ty]);
dfs(tx, ty);
v[tx][ty] = 0;
west[tx]--;
north[ty]--;
p.pop_back();
}
}
}
int main() {
cin >> n;
int t = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
arr[i][j] = t;
t++;
}
}//直接进行标号
for (int i = 1; i <= n; ++i) {
cin >> north_tr[i];
}
for (int i = 1; i <= n; ++i) {
cin >> west_tr[i];
}
west[1]++;
north[1]++;
v[1][1] = 1;
p.push_back(arr[1][1]);
dfs(1, 1);
return 0;
}
15 届蓝桥杯 14 天省赛冲刺营 1 期 - 最大数字 - 蓝桥云课 (lanqiao.cn)
错解:模拟 对于前面的数字尽可能让他大 对于0,1,2,3都是倒着走更快
对于0123如果可以倒着回去那就倒着回去
如果不是0123或不能倒着回去那就正着走 分为能不能到9
如果正着走完了那考虑倒着走
问题在于对于一个数我们不能确定倒着走还是正着走 因为就算对于0123这些书倒着走更快 但是如果后面的数更需要倒着走呢?所以我们要对于每个数达到最大值的过程 我们要试这两种情况然后取最大值才行
#include <bits/stdc++.h>
using namespace std;
#define cx first
#define cy second
const int N=1e2+7;
typedef pair<int,int> PII;
char backup[N][N];
int n,m;
int d;
int xx[]={1,-1,0,0};
int yy[]={0,0,-1,1};
int a,b;//可以执行操作a a次 操作b b次
//4->9需要5次操作
map<int,int>mp;
string s;
int len;//再输入后再获取长度
int ans[N];//记录答案
void dfs(int dep,int aa,int bb){
if(dep==len)return ;
if(aa==a&&bb==b){
for(int i=dep;i<len;i++){
ans[i]=s[i]-'0';
}
return ;
}
if(s[dep]=='9'){
ans[dep]=9;
dfs(dep+1,aa,bb);
}
else if(mp.find(s[dep]-'0')!=mp.end()&&((b-bb)>=mp[s[dep]-'0'])){//如果找到了且又能力让他退到最大
bb+=mp[s[dep]-'0'];
ans[dep]=9;//直接变为9
dfs(dep+1,aa,bb);
}
else{//如果没有能力让他退到最大那就加
int d=9-(s[dep]-'0');//最多加d
if(a-aa>=d){//如果可以做到让他加到9
aa+=d;
ans[dep]=9;
dfs(dep+1,aa,bb);
}else{//如果不能做到让他加到9
//那就试试能不能让他减到9如果不能那就算了
if(b-bb>=(s[dep]-'0')+1){
bb+=s[dep]-'0'+1;
ans[dep]=9;
dfs(dep+1,aa,bb);
}else{int temp=s[dep]-'0';//目前是temp
int add=a-aa;
aa=a;
ans[dep]=temp+add;
dfs(dep+1,aa,bb);}
}
}
}
void solve(){
cin>>s;
cin>>a>>b;
len=s.size();
mp[0]=1;mp[1]=2;mp[2]=3;mp[3]=4;//退回去到最大需要多少步
//对于每个数字如果<4的话就看下能不能退到9 如果不能那么加是最好的选择
//对于每个数字如果>=4那么就加
//如果是9那么就不动
dfs(0,0,0);//表示现在该看第dep位了目前已经用了多少次a和b技能了
for(int i=0;i<len;i++)cout<<ans[i];
}
int main(){
int t=1;
while(t--)solve();
return 0;
}
正确做法:对一个数我们试两种方法
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
char c[20];
LL ans=0;
//n:1号操作剩余次数 m:2号操作剩余次数
int n,m;
void dfs(int i,LL v){
int x=c[i]-'0';
if(c[i]){//这个位置有效的话
//应该使用的操作次数
int t=min(n,9-x);//剩余的操作次数 和对这个数最多能操作的次数取个小
n-=t;
dfs(i+1,v*10+x+t);//搜下一位
//回溯
n+=t;
//考虑操作2是否能够使用
if(m>x){//如果能退回去
m-=x+1;//那么就试试退回去
dfs(i+1,v*10+9);
//回溯
m+=x+1;
}
}else{
//答案取max
ans=max(ans,v);
}
}
int main() {
scanf("%s%d%d",c,&n,&m);
dfs(0,0);
printf("%lld\n",ans);
return 0;
}
15 届蓝桥杯 14 天省赛冲刺营 1 期 - 长草 - 蓝桥云课 (lanqiao.cn)
//同灌溉 注意时间上别弄乱了
#include <bits/stdc++.h>
using namespace std;
#define cx first
#define cy second
const int N=1e3+7;
typedef pair<int,int> PII;
char a[N][N];
char backup[N][N];//a的下一次
int n,m;
int d;
int xx[]={1,-1,0,0};
int yy[]={0,0,-1,1};
bool check(int x,int y){
if(x<1||y<1||x>n||y>m)return 0;
return 1;
}
void dfs(int x,int y){
for(int i=0;i<4;i++){
int tx=x+xx[i];
int ty=y+yy[i];
if(check(tx,ty)){
backup[tx][ty]='g';
}
}
return ;
}
//上一次是a数组 下一次是backup数组
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
cin>>d;
memcpy(backup,a,sizeof a);//先给backup赋个初值
while(d--){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]=='g'){
dfs(i,j);
}
}
}
memcpy(a,backup,sizeof backup);//即使将这次的转移给a做上一次的情况
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cout<<a[i][j];
}
cout<<'\n';
}
}
int main(){
int t=1;
while(t--)solve();
return 0;
}
//求最值问题都用bfs
#include <bits/stdc++.h>
using namespace std;
#define cx first
#define cy second
const int N=1e2+7;
typedef pair<int,int> PII;
int a[N][N];
int n,m;
int x2,y2;
int xx[]={1,-1,0,0};
int yy[]={0,0,-1,1};
int dp[N][N];//表示走到这个位置走了多少步
bool check(int x,int y){
if(x<1||y<1||x>n||y>m)return 0;
if(a[x][y]==0)return 0;
if(dp[x][y]!=-1)return 0;
return 1;
}
void bfs(int x,int y){
queue<PII>q;//队列
q.push({x,y});//初始化队列
while(q.size()){
PII cur=q.front();
q.pop();//记得要及时pop()不然会死循环
for(int i=0;i<4;i++){
int tx=cur.cx+xx[i];
int ty=cur.cy+yy[i];
if(check(tx,ty)){
dp[tx][ty]=dp[cur.cx][cur.cy]+1;//从那一步转移过来
q.push({tx,ty});
}
}
}
}
void solve(){
cin>>n>>m;
memset(dp,-1,sizeof dp);//初始化为-1
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
int x1,y1;
cin>>x1>>y1>>x2>>y2;
dp[x1][y1]=0;//及时赋初值
bfs(x1,y1);
cout<<dp[x2][y2];
}
int main(){
int t=1;
while(t--)solve();
return 0;
}