dfs和bfs

几个例题
1.最小转弯问题
题意:从起点出发到终点所需的最小转弯数
其实就是一行一行地bfs,有几个小细节。
主要还是bfs用队列实现的问题

void bfs(int x,int y){
//其实就是添加队首操作,记得初始化step
 now.x=x;
 now.y=y;
 now.step=0;
 q.push(now);
 while(!q.empty()){
  node next;
  //为啥oj不认我的二维方向数组呢?? 
  for(int k=0;k<4;k++){
   no = q.front();
   next.x =no.x+nextx[k];
   next.y=no.y+nexty[k];
     
   while(next.x>0&&next.x<=n&&next.y>0&&next.y<=m
   &&!map[next.x][next.y])
   {
   //注意点一:因为是一行一行直接bfs的,有可能会走过头so我们修改都时候要带上vis过的点哦
   //不然就没法回头了,所以vis要拿出来单独判断
   if(!vis[next.x][next.y]){
    
   if(next.x==tx&&next.y==ty){
   //注意点二:这里的step是上一个的 因为本次不需要转弯就到达了终点
   cout<<no.step<<endl;
   return;
   }
  
  vis[next.x][next.y]=1;
   next.step =no.step+1;
   q.push(next);
   }
   
   next.x+=nextx[k];
   next.y+=nexty[k];
   } 
  }
  //注意位置ang
  q.pop();
 }
 return ;
}

2.数独数独
九个小格子判断那里有点意思,像映射思想,
其实是构造了二元分段函数来的,分别对应那9个小格子

#include<iostream>
using namespace std;
int m[10][10];
bool visc[10][10],visr[10][10],visg[10][10];
//vis 是 1-9 列/行/小方格 中 1-9 是否出现过
void print(){
    for(int i=1;i<=9;i++){
            for(int j=1;j<=9;j++){
                        cout << m[i][j]<<" ";
                  }       
        cout << endl;}
}
void dfs(int x,int y){//x行y列    
if(m[x][y]!=0){        
if(x==9&&y==9) {            
print();        
}        //x行9列已搜完 搜x+1行
else if(y==9) dfs(x+1,1);
else dfs(x,y+1);    }       
if(m[x][y]==0){        
for(int i=1;i<=9;i++){            
if(!visr[x][i]&& !visc[y][i]&&            
!visg[(x-1)/3*3+(y-1)/3+1][i]){               
 m[x][y]=i;                
 visr[x][i]=1;                
 visc[y][i]=1;                
 visg[(x-1)/3*3+(y-1)/3+1][i]=1;                                
 if(x==9&&y==9){                    
 print();                }                
 else if(y==9) dfs(x+1,1);                                
 else dfs(x,y+1);                                
 m[x][y]=0;                
 visr[x][i]=0;                
 visc[y][i]=0;                
 visg[(x-1)/3*3+(y-1)/3+1][i]=0;            }        }    }}
 
int main(){        
for(int i=1;i<=9;i++){         
for(int j=1;j<=9;j++)            {   
cin>>m[i][j];                
if(m[i][j]>0){                    
visr[i][m[i][j]]=1;                    
visc[j][m[i][j]]=1;                    
visg[(i-1)/3*3+(j-1)/3+1][m[i][j]]=1;                }            }    }     
dfs(1,1);}

2.单词方阵
题意 在一个字符方阵里找到给定字符串并高亮显示
dfs快乐 记得每一次要搜八个方向 中途不可换方向哦 一开始没发现自己错在哪里
要开一个结构存储目前路径啊

//x,y目前位置 id是字符序号 当前正要匹配哪一个,d 是方向有8个,要枚举
void dfs(int x,int y,int id,int d){
 if(x<1||x>n||y<1||y>n) return;
 
 if(id>6){
  for(int i=0;i<=6;i++){
  // cout<<temp[6].x<<" "<<temp[6].y<<endl;
   book[temp[i].x][temp[i].y]=1;
  // if(book[1][7])cout<<book[1][7]<<endl;
  }
  return;
 }
 
 else{
 int tx=x+next[d][0];
 int ty=y+next[d][1];
// if(tx<0||tx>n||ty<0||ty>n) return;
 if(map[tx][ty]==t[id]){
  temp[id].x=tx;
  temp[id].y=ty;
  dfs(tx,ty,id+1,d); 
 }}
 return ;
}

3.洛谷p1441
有多种实现
先上一个超时的bfs吧。

#include<iostream>
#include<cmath>
#include<string.h>
#include<iomanip>
#include<queue>
using namespace std;
struct p{
 int x;int y;
};
//bfs当然是要用队列的
queue <p>xx ;
int n,m,sx,sy;
int next[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int a[10005][10005];
bool vis[10005][10005];
int main(){
 cin>>n>>m;
 for(int i=1;i<=n;i++){
  string x;cin>>x;
  for(int j=1;j<=n;j++){
   a[i][j]=x[j-1]-'0';
  }
 }
  
 p t;
 for(int i=1;i<=m;i++){
  int ans=1;
  while(!xx.empty())xx.pop();
  memset(vis,0,sizeof(vis));
  cin>>t.x>>t.y;
  xx.push(t);
  vis[t.x][t.y]=1;
  while(!xx.empty()){
  //如果放在最后就不对啦,因为最后一个点还没统计就pop了,这时候已经空了,跳出循环
  //所以会错掉
  //注意这个pop位置很玄妙,没有测试数据我根本调不出来= =。
  xx.pop();
  for(int k=0;k<4;k++){
   p g;
   g.x=t.x+next[k][0];
   g.y=t.y+next[k][1];
   if(g.x>=1&&g.x<=n&&
   g.y>=1&&g.y<=n&&!vis[g.x][g.y]){
    if(a[g.x][g.y]!=a[t.x][t.y]){
    vis[g.x][g.y]=1;
    xx.push(g);
    ans++;
    }
   else continue;
   }
  }
  t = xx.front();
  }
  
  cout<<ans<<endl; 
 }
}

emm然后是统计联通块的bfs不超时了

#include<iostream>
#include<cmath>
#include<string.h>
#include<iomanip>
#include<queue>
using namespace std;
struct p{
 int x;int y;
};
queue <p>xx ;
int n,m,sx,sy;
int next[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int a[10005][10005];
//把vis改成int用来记录联通块的序号
int vis[10005][10005];
//ans预处理存储答案,询问时直接输出
int ans[100000005];

int main(){
 int d=0;
 cin>>n>>m;
 for(int i=1;i<=n;i++){
  string x;cin>>x;
  for(int j=1;j<=n;j++){
   a[i][j]=x[j-1]-'0';
  }
 } 
 //预处理一般是每个点都遍历一下的,这样才能加快速度啊
 //多组数据要记得初始化。
 for(int i=1;i<=n;i++){
  for(int j=1;j<=n;j++){
   if(!vis[i][j]){
   d++;
   p t;
   t.x=i;t.y=j;
   //vis[t.x][t.y]=1;
   xx.push(t);
   int sum=0;
   while(!xx.empty()){ 
    p g;
    
    for(int k=0;k<4;k++){
     g.x=t.x+next[k][0];
     g.y=t.y+next[k][1];
     //注意还是要判断重复,不然会死循环
     if(!vis[g.x][g.y]&&
     g.x>=1&&g.x<=n&&
     g.y>=1&&g.y<=n){
      if(a[g.x][g.y]!=a[t.x][t.y]){
       sum++;
       vis[g.x][g.y]=d;
       xx.push(g);  
      }
     }
    }
    xx.pop();
    t=xx.front();
   }
   //每个联通块里面每个点的答案是一样的
   ans[d]=sum; 
   }   
  }
 }
  for(int i=1;i<=m;i++){
  int x,y;
  cin>>x>>y;
  if(ans[vis[x][y]])  
  cout<<ans[vis[x][y]]<<endl;
  //如果那个地方找不到的话,因为我bfs写得太垃圾的原因是走不到1的,所以我们手动调整一下。。
  else cout<<1<<endl;
 }
}

4.这几天又做了一个妙绝的数独。
洛谷p1074靶型数组,是数独的更快解法,之前那个虽然工整,但是慢。
要求先搜已知项最多的行与列,可以减少尝试,这样之前数独就不行了,因为那个是一行一行按顺序搜,所以跳出条件改成统计有效数字个数=81,每次选取下一个都优化一下,具体实现看码
真的神仙啊!还有舞蹈链做法(自带剪枝的神秘数据结构),不过还没打算研究。

#include<iostream>
#include<cmath>
#include<string.h>
#include<stdio.h>
#include<iomanip>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
int map[10][10];
int vx[10][10];
int vy[10][10];
int vg[10][10];
int ans=-1;
int t[10][10];
int c_x[10],c_y[10];
//算加权的
int cal(){
    int sum=0;
    for(int i=1;i<=9;i++){
        for(int j=1;j<=9;j++){
            if(i==1||i==9||j==1||j==9){
                sum+=6*t[i][j]; 
            }
            else if(i==2||i==8||j==2||j==8){
                sum+=7*t[i][j];
            }
            else if(i==3||i==7||j==3||j==7){
                sum+=8*t[i][j];
            }
            else if(i==4||i==6||j==4||j==6){
                sum+=9*t[i][j];
            }
            else if(i==5&&j==5) sum+=10*t[i][j];
        }
    }
    return sum;
}
//啊!
void dfs(int x,int y,int cnt){ 
 if(cnt==81){
  ans = max(ans,cal());
  return;
 }
    else
    for(int i=1;i<=9;i++){
        if(!vx[x][i]&&!vy[y][i]&&!vg[3*((x-1)/3)+(y-1)/3+1][i]){
            t[x][y]=i;
            vx[x][i]=1;
            vy[y][i]=1;
            vg[3*((x-1)/3)+(y-1)/3+1][i]=1;
            //这两个就是记录每行非0的个数了
            c_x[x]++; c_y[y]++;
            
            int nx=0,ny=0,mx=-1,my=-1;
            for(int j=1;j<=9;j++){
             if(c_x[j]>mx&&c_x[j]<9)
              mx=c_x[j],nx=j;
            }
            //先把nx确定下来,再在nx行找ny
            for(int j=1;j<=9;j++){
             if(c_y[j]>my&&!t[nx][j])
              my=c_y[j],ny=j;
            }
            dfs(nx,ny,cnt+1);            
            t[x][y]=0;
            vx[x][i]=0;
            vy[y][i]=0;
            vg[3*((x-1)/3)+(y-1)/3+1][i]=0;
            c_x[x]--;
            c_y[y]--;
        }
    } 
}
int cnt=0;
int main(){
    for(int i=1;i<=9;i++){
        for(int j=1;j<=9;j++){
            cin>>map[i][j];
            if(map[i][j]>0) {
             cnt++;//记得加初始已知项啊 不然无解。
                t[i][j]=map[i][j];
                vx[i][map[i][j]]=1;
                vy[j][map[i][j]]=1;
                c_x[i]++;c_y[j]++;
                vg[3*((i-1)/3)+(j-1)/3+1][map[i][j]]=1;
            }
        }
    }
    //重复一遍,其实写个函数更好看写i
            int nx,ny,mx=-1,my=-1;
            for(int i=1;i<=9;i++){
             if(c_x[i]>mx&&c_x[i]<9)
               mx=c_x[i],nx=i;
            }
            for(int i=1;i<=9;i++){
             if(c_y[i]>my&&!t[nx][i])
              my=c_y[i],ny=i;
            }
    //print();
    dfs(nx,ny,cnt);
    cout <<ans<<endl;
}

5.洛谷幻想迷宫
一个有点小要求的dfs
为了判断是不是走过,新开了数组记录取模前的原始数据

#include <cstdio>
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm> 
#include<iomanip>
#include<cmath>
using namespace std;
int n,m,sx,sy;
bool ans=0;
char mp[2000][2000];
int book[2000][2000][3];
bool vis[2000][2000];
int nxt[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
void dfs(int x,int y,int lx,int ly){
 if(ans) return ;
 if(vis[x][y]&&(book[x][y][1]!=lx||book[x][y][2]!=ly)){
  ans =1;
  return;
 }
 book[x][y][1]=lx;
 book[x][y][2]=ly;
 vis[x][y]=1;
 for(int k=0;k<4;k++){
  int nx=x+nxt[k][0];
  int ny=y+nxt[k][1];
  if(nx==0) nx=n;
  if(nx==n+1) nx=1;
  if(ny==0) ny=m;
  if(ny==m+1) ny=1;
  //这里的lxx记得要新建,不可在lx上改动啊  不然出了循环就gg
  int lxx = lx+nxt[k][0];
  int lyy = ly+nxt[k][1];
  if(mp[nx][ny]=='.'||mp[nx][ny]=='S'){
   if(book[nx][ny][1]!=lxx||book[nx][ny][2]!=lyy||!vis[nx][ny]){
    dfs(nx,ny,lxx,lyy);
   }
  }
 }
}
int main(){
 while(cin>>n>>m){
  ans =0;
  for(int i=1;i<=n;i++){
   for(int j=1;j<=m;j++){
    mp[i][j]='0';
    book[i][j][1]=0;
    book[i][j][2]=0;
    vis[i][j]=0;
   }
  }
  for(int i=1;i<=n;i++){
   for(int j=1;j<=m;j++){
    cin>>mp[i][j];
    if(mp[i][j]=='S'){
     sx=i;sy=j;
    }
   }
  }
  dfs(sx,sy,sx,sy);
  if(ans) cout<<"Yes"<<endl;
  else cout << "No"<<endl;
 }
 return 0;
}

6.P1363 创意吃鱼法
(1)给个我的辣鸡超时版 暴力dfs 剪枝无能QwQ

#include <cstdio>
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm> 
#include<iomanip>
#include<cmath>
using namespace std;
int n,m,ans,maxnn;
int mp[3000][3000];
bool dfs(int x,int y,int k){
 if(k==1){
  if(mp[x][y]) {
   ans = max(ans,1);
   return 1;
  }
  else return 0;
 }
 if(ans>=k) return 0;
 bool f1=1,f2=1;
 for(int i=x;i<=x+k-1;i++){
  if(!f1) break;
  for(int j=y;j<=y+k-1;j++){
   if(i-x==j-y){
    if(!mp[i][j]){
     f1=0;
     break;
    }
   }
   else {
    if(mp[i][j]){
     f1=0;
     break;
    }
   }
  }
 }
 for(int i=x;i<=x+k-1;i++){
  if(!f2) break;
  for(int j=y;j<=y+k-1;j++){
   if(i-x+j-y==k-1){
    if(mp[i][j]==0){
     f2=0;
     break;
    }
   }
   else{
    if(mp[i][j]==1){
     f2=0;
     break;
    }
   }
  }
 }
 if(f1||f2){
  ans = max(ans,k);
  return 1;
 }
 else return 0;
}
int main(){
 cin >> n>>m;
 for(int i=1;i<=n;i++){
  for(int j=1;j<=m;j++){
   cin >> mp[i][j];
  }
 }
 for(int i=1;i<=n;i++){
  if(ans>=n-i+1)break;
  for(int j=1;j<=m;j++){
   if(ans>=m-j+1) break;
   for(int k=min(n-i+1,m-j+1);k>=1;k--){
    if(k<ans) break;
    if(dfs(i,j,k)){
     //cout << i <<" "<<j<<" "<<k<<endl;
     break;
    }
   }
  }
 }
 cout << ans <<endl;
 return 0;
}

(2)正解 我觉得妙(前缀预处理加速 分两种情况判断:对角线和右对角线)

#include <cstdio>
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm> 
#include<iomanip>
#include<cmath>
using namespace std;
int n,m,ans;
int mp[3000][3000];
int s[3000][3000];
void workl(){
 for(int i=1;i<=n;i++){
  for(int j=1;j<=m;j++){
   int k=0;
   while(1){
    k++;
    //(i,j)是左上顶点 对角线向右向下
    if(k+i-1>n||k+j-1>m) break;
    if(s[i+k-1][j+k-1]-s[i+k-1][j-1]-s[i-1][j+k-1]+s[i-1][j-1]==k){
     if(mp[i][j]&&mp[i+k-1][j+k-1])  ans = max(ans,k);
     else break; 
    }
    else break;
   }
  }
 }
}
void workr(){
 for(int i=1;i<=n;i++){
  for(int j=1;j<=m;j++){
   int k=0;
   while(1){
    k++;
    //(i,j)是右上顶点 对角线向左向下
    if(k+i-1>n||j-k+1<=0) break;
    if(s[i+k-1][j]-s[i+k-1][j-k]-s[i-1][j]+s[i-1][j-k]==k){
     if(mp[i][j]&&mp[i+k-1][j-k+1]) ans=max(ans,k);
     else break;
    }
    else break;
   }
  }
 } 
}
int main(){
 cin >> n>>m;
 for(int i=1;i<=n;i++){
  for(int j=1;j<=m;j++){
   cin >> mp[i][j];
  }
 }
 //处理前缀和
 for(int i=1;i<=n;i++){
  for(int j=1;j<=m;j++){
   s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+mp[i][j];
  }
 }
 workl();
 workr();
 cout << ans <<endl;
 return 0;
}

(3)dp版

#include <cstdio>
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm> 
#include<iomanip>
#include<cmath>
using namespace std;
int n,m,ans;
const int inf=0x3f3f3f3f;
int mp[3000][3000];
int dp[3000][3000];
void up(){
 for(int i=1;i<=n;i++){
  for(int j=1;j<=m;j++){
   ans = max(ans,dp[i][j]);
  }
 } 
}
void ini(){
 for(int i=1;i<=n;i++){
  for(int j=1;j<=m;j++){
   dp[i][j]=mp[i][j];
  }
 }
}
void workl(){
 ini();
 for(int i=1;i<=n;i++){
  for(int j=1;j<=m;j++){
   if(mp[i][j]&&dp[i-1][j-1]){
    bool f=1;int l=inf;
    for(int k=i-1;k>=i-dp[i-1][j-1]&&f;k--){
     if(mp[k][j]) f=0,l=min(l,i-k);
    }
    for(int k=j-1;k>=j-dp[i-1][j-1]&&f;k--){
     if(mp[i][k]) f=0,l=min(l,j-k);
    }
    if(f) dp[i][j]=dp[i-1][j-1]+1;
    else dp[i][j]=l;
   }
  }
 }
 up();
}
void workr(){
 ini();
 for(int i=1;i<=n;i++){
  for(int j=m;j>=1;j--){
   if(mp[i][j]&&dp[i-1][j+1]){
    bool f=1;int l=inf;
    for(int k=j+1;k<=j+dp[i-1][j+1]&&f;k++){
     if(mp[i][k]) f=0,l=min(l,k-j);
    }
    for(int k=i-1;k>=i-dp[i-1][j+1]&&f;k--){
     if(mp[k][j]) f=0,l=min(l,i-k);
    }
    if(f) dp[i][j]=dp[i-1][j+1]+1;
    else dp[i][j]=l;
   }
  }
 }
 up();
}
int main(){
 cin >> n>>m;
 for(int i=1;i<=n;i++){
  for(int j=1;j<=m;j++){
   cin >> mp[i][j];
  }
 }
 workl();
 workr();
 cout << ans <<endl;
 return 0;
}

7.中规中矩的dfs 洛谷P1120
很巧妙的剪枝和预处理

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <cmath>
#include<algorithm>
using namespace std;
int n,cnt,sum,a[70],num,per,nxt[70];
bool f=0,vis[70];
//k是当前木棍数,last上一个木棍方便撤回,res当前木棍剩余量 
void dfs(int k,int last,int res){
 if(f) return;
 if(res==0){
  if(k==num){
   f=1;
   return ;
  }
  int t;
  for(int i=1;i<=cnt;i++){
   if(!vis[i]){
    t=i;
    break;
   }
  }
  vis[t]=1;
  dfs(k+1,t,per-a[t]);
  vis[t]=0;
  if(f) return ;
 } 
 //找出第一个长度<=res的位置 
 int l=last+1,r=cnt;
 int mid;
 while(l<r){
  mid=(l+r)>>1;
  if(a[mid]<=res) r=mid;
  else l=mid+1;
 }
 for(int i=l;i<=cnt;i++){
  if(!vis[i]){
   vis[i]=1;
   dfs(k,i,res-a[i]);
   vis[i]=0;
   if(f) return ;
   //如果剩下的拼不出想要的长度,
   if(res==a[i]||a[i]==per) return;
   i=nxt[i];
   if(i==cnt) return;
  }
 }
} 
bool cmp(int x,int y){
 return x>y;
}
int main(){
 cin>>n;
 for(int i=1;i<=n;i++){
  int x;
  cin>>x;
  //题目条件看错了,我...... 
  if(x<=50) {
  a[++cnt]=x;
  sum+=x;
  }
 }
 //预处理 按倒序排列 这样先拼大的再用小的拼出大的,总是有解的
 //但是如果乱序,先拼小的,后面大的是没用的 
 sort(a+1,a+1+cnt,cmp);
 //nxt预处理,如果dfs时候一根木棍不行那么后面与它长度相等的也不行
 nxt[cnt]=cnt;
 for(int i=cnt-1;i>0;i--){
  if(a[i]==a[i+1]) nxt[i]=nxt[i+1];
  else nxt[i]=i;
 } 
 //开始枚举 (maxn,sum)
 for(int i=a[1];i<=sum/2;i++){
  if(sum%i==0){
   f=0;
   per=i;
   num=sum/per;
   vis[1]=1;
   dfs(1,1,per-a[1]);
   vis[1]=0;
   if(f){
    cout<<per<<endl;
    return 0;
   }
  }
 }
 cout<<sum<<endl; 
 return 0;
}
  1. dfs 水 P2404
    我已经无聊到做这种题来消磨时间了吗

#include <iostream>
#include <string>
#include <cstdlib>
#include <queue>
#include <stack>
#include<vector>
#include"string.h"
#include"string"
#include <map>
#include <sstream>
#include <iomanip>
#include <algorithm>
#define INF 0x7fffffff
#define lson num << 1
#define rson num << 1 | 1
using namespace std;
const int  maxn = 1e3 + 5;
int n;
int book[10];
void work(int last,int cur, int target,string s) {
	if (cur > target) return;
	if (cur == target && last != target) {
		cout <<s<< endl;
		return;
	}
	for (int i = last;i <= target - cur;i++) {
		string tmp = s;
		s += char('0' + i);
		if(cur+i != target) s += '+';
		work(i,cur + i, target,s);
		s = tmp;
	}
}
int main(){
	cin >> n;
	work(1,0, n, "");
	return 0;
}

P1433
TSP问题鸭,竟然没想出来,其实容易被思维定势
正解是状压dp,dfs挂了最后一个点
(1)DFS(WA的

#include <iostream>
#include <string>
#include <cstdlib>
#include <queue>
#include <stack>
#include<vector>
#include"string.h"
#include"string"
#include <map>
#include <sstream>
#include <iomanip>
#include <algorithm>
#define INF 0x7fffffff
#define lson num << 1
#define rson num << 1 | 1
using namespace std;
const int  maxn = 1e3 + 5;
int n;
double ans = INF;
bool vis[maxn];
struct P {
	double x, y;
}p[maxn];
double dis(P p1, P p2) {
	double res = 0;
	res = sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
	return res;
}
bool check() {
	for(int i = 1;i <= n;i++) {
		if (!vis[i]) return false;
	}
	return true;
}
void dfs(int id,double tot) {
	if (tot >= ans) return;
	if (check()) {
		ans = min(ans, tot);
		return;
	}
	for (int i = 1;i <= n;i++) {
		if (!vis[i]) {
			vis[i] = 1;
			dfs(i, tot + dis(p[id], p[i]));
			vis[i] = 0;
		}
	}
	return;
}
int main(){
	cin >> n;
	p[0].x = p[0].y = 0;
	for (int i = 1;i <= n;i++) {
		cin >> p[i].x >> p[i].y;
	}
	dfs(0,0);
	cout << fixed << setprecision(2)<<ans << endl;
	return 0;
}

(2)状压DP
要记得初始化和处理边界条件


#include <iostream>
#include <string>
#include<cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include<vector>
#include"string.h"
#include"string"
#include <map>
#include <sstream>
#include <iomanip>
#include <algorithm>
#define INF 0x7fffffff
#define lson num << 1
#define rson num << 1 | 1
using namespace std;
const int  maxn = 1e3 + 5;
const int N = 20;
int n;
double ans = INF;
bool vis[maxn];
double dp[20][1 << 20];
struct P {
	double x, y;
}p[maxn];
double dis(P p1, P p2) {
	double res = 0;
	res = sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
	return res;
}
bool check() {
	for (int i = 1;i <= n;i++) {
		if (!vis[i]) return false;
	}
	return true;
}
void dfs(int id, double tot) {
	if (tot >= ans) return;
	if (check()) {
		ans = min(ans, tot);
		return;
	}
	for (int i = 1;i <= n;i++) {
		if (!vis[i]) {
			vis[i] = 1;
			dfs(i, tot + dis(p[id], p[i]));
			vis[i] = 0;
		}
	}
	return;
}
int main() {
	//cout << (1 << 20) << endl;
	cin >> n;
	p[0].x = p[0].y = 0;
	for (int i = 1;i <= n;i++) {
		cin >> p[i].x >> p[i].y;
	}
	for (int i = 1;i <= (1 << n);i++) {
		for (int j = 1;j <= n;j++) {
			dp[j][i] = INF;
		}
	}
	for (int s = 1;s <=(1 << n)-1;s++) {
		for (int i = 1;i <= n;i++) {
			//如果没有挑选第i个,跳过
			if ((s&(1 << (i - 1))) == 0)continue;
			//以i为开头,后面还暂时没有(边界)
			if (s == (1 << (i - 1))) { dp[i][s] = 0;continue; }
			for (int j = 1;j <= n;j++) {
				if (!((s&(1 << (j - 1))) == 0 || i == j)) {
					dp[i][s] = min(dp[i][s], dp[j][s - (1 << (i - 1))] + dis(p[i], p[j]));
				}	
				
			}	
		}
	}
	for (int i = 1;i <= n;i++) {
		ans = min(ans, dp[i][(1 << n) - 1] + dis(p[0], p[i]));
	}
	cout << fixed << setprecision(2) << ans << endl;
	return 0;
}

P1825
BFS,没看出坑在哪里,但是我写挂了

#include <iostream>
#include <string>
#include <cstdlib>
#include <queue>
#include <stack>
#include<vector>
#include"string.h"
#include"string"
#include <map>
#include <sstream>
#include <iomanip>
#include <algorithm>
#define INF 0x7fffffff
#define lson num << 1
#define rson num << 1 | 1
using namespace std;
const int  maxn = 1e3 + 5;
int n, m,sx,sy,ex,ey,ans;
struct P {
	int x, y,t;
	P(int xx, int yy,int tt) {
		x = xx;y = yy;t = tt;
	};
	P(){};
};
struct Door {
	P p1, p2;
	int cnt;
}door[maxn];
int nxt[4][2] = { {0,1},{0,-1},{1,0},{-1,0}};
char mp[505][505];
bool vis[505][505];
P fuk(P t) {
	P res;
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= m;j++) {
			if (mp[t.x][t.y] == mp[i][j] && (i != t.x || j !=t.y)) {
				res.x = i;
				res.y = j;
				res.t = t.t;
				return res;
			}
		}
	}
}
void bfs() {
	queue<P> q;
	q.push(P(sx, sy, 0));
	while (!q.empty()) {
		P u = q.front();
		q.pop();
		if (mp[u.x][u.y] == '=') {
			cout << u.t << endl;
			return;
		}
		if (mp[u.x][u.y] >= 'A' && mp[u.x][u.y] <= 'Z') {
			u = fuk(u);
		}
		for (int k = 0;k < 4;k++) {
			int nx = u.x + nxt[k][0];
			int ny = u.y + nxt[k][1];
			if (nx >= 1 && nx <= n && ny >= 1 && ny <= m
				&& mp[nx][ny] != '#' && !vis[nx][ny]) {
				vis[nx][ny] = 1;
				q.push(P(nx, ny, u.t + 1));
			}
		}
	}
}
int main() {
	cin >> n >> m;
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= m;j++) {
			cin >> mp[i][j];
			if (mp[i][j] == '@') {
				sx = i;sy = j;
			}
		}
	}
	bfs();
	return 0;
}

P1032 字符串拼接
噢老天爷我为什么要用dfs,bfs不香吗
又wa又t的dfs,我lay了
学习了双向bfs,挺好


//感谢logu 大佬 BrandonSoong
#include"pch.h"
#include <iostream>
#include <string>
#include <cstdlib>
#include <queue>
#include <stack>
#include<vector>
#include"string.h"
#include"string"
#include <map>
#include <sstream>
#include <iomanip>
#include <algorithm>
#define INF 0x7fffffff
#define lson num << 1
#define rson num << 1 | 1
using namespace std;
const int  maxn = 1e3 + 5;
string A, B;
int num = 0, begin_pos = 0, end_pos = 0;
struct P {
	string u, v;
}p[maxn];
bool flag = 0;
map<string,int> mp;
string replace(string a, string cur) {
	string res = "";
	for (int i = 0;i < begin_pos;i++)
		res += cur[i];
	res += a;
	for (int i = end_pos + 1;i < cur.length();i++)
		res += cur[i];
	return res;
}
bool issub(string a, string A) {
//	cout << "is "<<a<<" the substring of" << A << endl;
	int nxt = begin_pos = end_pos = 0;
	for (int i = 0;i < A.length();i++) {
		int start = i;
		int j = 0;
		while (j < a.length()) {
			if (A[start + j] != a[j]) break;
			j++;
		}
		if (j == a.length()) {
			begin_pos = i;
			end_pos = begin_pos + a.length() - 1;
			return 1;
		}
	}
	return 0;
}
struct PP {
	int t;
	string s;
	PP(string ss,int tt) {
		t = tt;
		s = ss;
	}
	PP() {};
};
//这个bfs,挂了
void bfs() {
	queue<PP>q;
	mp[A] = 1;
	PP cur;cur.s = A;cur.t = 0;
	q.push(cur);
	while (!q.empty()&&!flag) {
		PP uu = q.front();
		if (uu.s == B) {
			flag = 1;
			cout << uu.t << endl;
			return;
		}
		if (uu.t > 10) return;
		q.pop();
		for (int i = 1;i <= num;i++) {
			if (issub(p[i].u, uu.s)) {
				string new_cur = replace(p[i].v,uu.s);
				if (!mp[new_cur]) {
					mp[new_cur] = 1;
					PP v;v.s = new_cur;v.t = uu.t + 1;
					if (new_cur == B) {
						flag = 1;
						cout << v.t << endl;
						return;
					}
					else {
						q.push(v);
					}
				}
			}
		}
	}
}
//
queue<string> a, b;
map<string, int> mpa, mpb;
int two_bfs() {
	int step = 0;
	a.push(A);b.push(B);
	mpa[a.front()] = 0; mpb[b.front()] = 0;
	//cout << mpa[A] << mpb[B] << endl;
	string s, s2;
	while (++step <= 5) {

		while (mpa[a.front()] == step - 1) {
			s = a.front();
			a.pop();
		
			for (int i = 1;i <= num;i++) {
				unsigned int pos = 0;
				while (pos < s.length()) {
					if (s.find(p[i].u, pos) == s.npos) {
						break;
					}
					s2 = s;
					s2.replace(s2.find(p[i].u, pos), p[i].u.length(), p[i].v);
					if (mpa.find(s2) != mpa.end()) {
						pos++;
						continue;
					}
					if (mpb.find(s2) != mpb.end()) {
						return 2 * step - 1;
					}
					a.push(s2);
					mpa[s2] = step;
					pos++;
				}
			}
		}

		while (mpb[b.front()] == step - 1) {
			s = b.front();
			b.pop();
			for (int i = 1;i <= num;i++) {
				unsigned int pos = 0;
				while (pos < s.length()) {
					if (s.find(p[i].v, pos) == s.npos) {
						break;
					}
					s2 = s;
					s2.replace(s2.find(p[i].v, pos), p[i].v.length(), p[i].u);
					if (mpb.find(s2) != mpb.end()) {
						pos++;
						continue;
					}
					//	cout <<"B: "<< nxts << endl;
					if (mpa.find(s2) != mpa.end()) {
						return 2 * step;
					}
					b.push(s2);
					mpb[s2] = step;
					pos++;
				}
			}
		}
	}
	return -1;
}
int main() {
	cin >> A >> B;
	string s1, s2;
	while (cin >> s1 >> s2) {
		p[++num].u = s1;
		p[num].v = s2;
	}
	int ans = two_bfs();
	if (ans != -1) cout <<ans << endl;
	else cout << "NO ANSWER!" << endl;
	return 0;
}

因为一句位置写错了,debug到半夜,累了睡了睡了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值