搜索算法

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;
}

 2.走迷宫 - 蓝桥云课 (lanqiao.cn)

//求最值问题都用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;
}

 

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值