来自:算法提高课
文章目录
第二讲 搜索
2.1 Flood Fill
2.1.1 1097. 池塘计数
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int n,m;
char g[N][N];
bool inq[N][N]={false};
int X[8]={0,0,1,-1,-1,1,-1,1};
int Y[8]={1,-1,0,0,1,1,-1,-1};
struct Node{
int x,y;
}node;
bool judge(int x,int y)
{
if(x>=n||x<0||y>=m||y<0)
{
return false;
}
if(g[x][y]=='.'||inq[x][y]==true)
{
return false;
}
return true;
}
void bfs(int x,int y)
{
queue<Node> q;
node.x=x,node.y=y;
q.push(node);
inq[x][y]=true;
while(!q.empty())
{
Node top=q.front();
q.pop();
for(int i=0;i<8;i++)
{
int newX=top.x+X[i];
int newY=top.y+Y[i];
if(judge(newX,newY))
{
node.x=newX,node.y=newY;
q.push(node);
inq[newX][newY]=true;
}
}
}
}
int main()
{
cin>>n>>m;
getchar();
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
char c=getchar();
g[i][j]=c;
}
getchar();
}
int ans=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(g[i][j]=='W'&&inq[i][j]==false)
{
ans++;
bfs(i,j);
}
}
}
cout<<ans;
return 0;
}
2.1.2 1098. 城堡问题
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=60;
int m,n;
int g[N][N][5];
bool inq[N][N];
int X[]={0,-1,0,1},Y[]={-1,0,1,0};
map<int,int> mp;
struct Node{
int x,y;
}node;
void init()
{
mp[0]=3;
mp[1]=4;
mp[2]=1;
mp[3]=2;
}
int judge(int x,int y,int flag)
{
if(x>=m||x<0||y>=n||y<0)
{
return false;
}
if(g[x][y][flag]==1||inq[x][y]==true)
{
return false;
}
return true;
}
int bfs(int x,int y)
{
int ans=1;
queue<Node> q;
node.x=x,node.y=y;
q.push(node);
inq[x][y]=true;
while(!q.empty())
{
Node top=q.front();
q.pop();
for(int i=0;i<4;i++)
{
int newX=top.x+X[i];
int newY=top.y+Y[i];
if(judge(newX,newY,mp[i]))
{
node.x=newX,node.y=newY;
q.push(node);
inq[newX][newY]=true;
ans++;
}
}
}
return ans;
}
int main()
{
cin>>m>>n;
init();
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
int x;
cin>>x;
g[i][j][1]=x&1;
g[i][j][2]=(x&2)>>1;
g[i][j][3]=(x&4)>>2;
g[i][j][4]=(x&8)>>3;
}
}
int ans=0,s=0;
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if(inq[i][j]==false)
{
ans++;
s=max(s,bfs(i,j));
}
}
}
cout<<ans<<endl<<s;
return 0;
}
2.1.3 1106. 山峰和山谷
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int n;
int g[N][N];
bool inq[N][N];
int X[]={0,0,1,-1,-1,-1,1,1},Y[]={1,-1,0,0,-1,1,-1,1};
struct Node{
int x,y;
}node;
bool judge(int x,int y,int sx,int sy)
{
if(x>=n||x<0||y>=n||y<0)
{
return false;
}
if(g[x][y]!=g[sx][sy]||inq[x][y]==true)
{
return false;
}
return true;
}
int bfs(int x,int y)
{
queue<Node> q,sv;
node.x=x,node.y=y;
q.push(node);
inq[x][y]=true;
sv.push(node);
while(!q.empty())
{
Node top=q.front();
q.pop();
for(int i=0;i<8;i++)
{
int newX=top.x+X[i],newY=top.y+Y[i];
if(judge(newX,newY,x,y))
{
node.x=newX,node.y=newY;
q.push(node);
inq[newX][newY]=true;
sv.push(node);
}
}
}
int h=0,l=0;
bool flagh=true,flagl=true;
while(!sv.empty())
{
Node top=sv.front();
sv.pop();
for(int i=0;i<8;i++)
{
int newX=top.x+X[i],newY=top.y+Y[i];
if(!(newX>=n||newX<0||newY>=n||newY<0))
{
if(g[x][y]<g[newX][newY])
{
flagh=false;
}
if(g[x][y]>g[newX][newY])
{
flagl=false;
}
}
}
}
if(flagh&&flagl)
{
return 2;
}
if(flagh)
{
return 1;
}
if(flagl)
{
return -1;
}
return 0;
}
int main()
{
ios::sync_with_stdio(0);
cin>>n;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin>>g[i][j];
}
}
int h=0,l=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(inq[i][j]==false)
{
int x=bfs(i,j);
if(x==2)
{
h++;
l++;
}
else if(x==1) h++;
else if(x==-1) l++;
}
}
}
cout<<h<<" "<<l;
return 0;
}
2.2 最短路模型
2.2.1 1076. 迷宫问题
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int n;
int g[N][N];
bool inq[N][N];
struct Node{
int x,y;
}node;
Node pre[N][N];
int X[]={0,0,1,-1},Y[]={1,-1,0,0};
bool judge(int x,int y)
{
if(x>=n||x<0||y>=n||y<0)
return false;
if(g[x][y]==1||inq[x][y]==true)
return false;
return true;
}
void bfs(int x,int y)
{
queue<Node> q;
node.x=x,node.y=y;
q.push(node);
inq[x][y]=true;
while(!q.empty())
{
Node top=q.front();
q.pop();
for(int i=0;i<4;i++)
{
int newX=top.x+X[i],newY=top.y+Y[i];
if(judge(newX,newY))
{
node.x=newX,node.y=newY;
q.push(node);
node.x=top.x,node.y=top.y;
pre[newX][newY]=node;
inq[newX][newY]=true;
}
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin>>g[i][j];
}
}
bfs(n-1,n-1);
node.x=0,node.y=0;
while(true)
{
cout<<node.x<<" "<<node.y<<endl;
if(node.x==n-1&&node.y==n-1)
break;
node=pre[node.x][node.y];
}
return 0;
}
2.2.2 188. 武士风度的牛
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=160;
int r,c;
int g[N][N];
bool inq[N][N];
int sx,sy,ex,ey;
int X[]={-2,-2,-1,-1,1,1,2,2};
int Y[]={-1,1,-2,2,2,-2,1,-1};
int dist[N][N];
struct Node{
int x,y;
}node;
bool judge(int x,int y)
{
if(x>=r||x<0||y>=c||y<0)
return false;
if(g[x][y]=='*'||inq[x][y]==true)
return false;
return true;
}
int bfs(int x,int y)
{
queue<Node> q;
node.x=x,node.y=y;
q.push(node);
inq[x][y]=true;
while(!q.empty())
{
Node top=q.front();
q.pop();
for(int i=0;i<8;i++)
{
int newX=top.x+X[i],newY=top.y+Y[i];
if(judge(newX,newY))
{
node.x=newX,node.y=newY;
dist[newX][newY]=dist[top.x][top.y]+1;
q.push(node);
inq[newX][newY]=true;
}
}
}
return dist[ex][ey];
}
int main()
{
cin>>c>>r;
getchar();
for(int i=0;i<r;i++)
{
for(int j=0;j<c;j++)
{
char ch=getchar();
if(ch=='K')
{
sx=i,sy=j;
}
if(ch=='H')
{
ex=i,ey=j;
}
g[i][j]=ch;
}
getchar();
}
cout<<bfs(sx,sy);
return 0;
}
2.2.3 1100. 抓住那头牛
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int n,k;
bool inq[N];
int dist[2*N];
int getX(int x,int flag)
{
if(flag==0)
x=2*x;
else if(flag==1)
x-=1;
else x+=1;
return x;
}
void bfs(int x)
{
queue<int> q;
q.push(x);
inq[x]=true;
dist[x]=0;
while(!q.empty())
{
int top=q.front();
q.pop();
for(int i=0;i<3;i++)
{
int newX=getX(top,i);
if(newX>=0&&newX<N&&inq[newX]==false)
{
q.push(newX);
inq[newX]=true;
dist[newX]=min(dist[newX],dist[top]+1);
}
}
}
}
int main()
{
cin>>n>>k;
fill(dist,dist+2*N,1e9);
bfs(n);
cout<<dist[k];
return 0;
}
2.3 多源BFS
2.3.1 173. 矩阵距离
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int n,m;
int g[N][N];
int dist[N][N];
int X[]={0,0,1,-1},Y[]={1,-1,0,0};
struct Node{
int x,y;
}node;
bool judge(int x,int y)
{
if(x>=n||x<0||y>=m||y<0)
return false;
if(g[x][y]=='1'||dist[x][y]!=-1)
return false;
return true;
}
void bfs()
{
fill(dist[0],dist[0]+N*N,-1);
queue<Node> q;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(g[i][j]=='1')
{
node.x=i,node.y=j;
dist[i][j]=0;
q.push(node);
}
}
}
while(!q.empty())
{
Node top=q.front();
q.pop();
for(int i=0;i<4;i++)
{
int x=top.x+X[i],y=top.y+Y[i];
if(judge(x,y))
{
node.x=x,node.y=y;
q.push(node);
dist[x][y]=dist[top.x][top.y]+1;
}
}
}
}
int main()
{
cin>>n>>m;
getchar();
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
g[i][j]=getchar();
}
getchar();
}
bfs();
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cout<<dist[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
2.4 最小步数模型
2.4.1 1107. 魔板
代码:
#include<bits/stdc++.h>
using namespace std;
char g[2][4];
string st,ed;
map<string,int> dis;
map<string,pair<char,string> > pre;
void toM(string str)
{
for(int i=0;i<4;i++)
{
g[0][i]=str[i];
}
for(int i=3,j=4;i>=0;i--,j++)
{
g[1][i]=str[j];
}
}
string getStr()
{
string str="";
for(int i=0;i<4;i++)
{
str+=g[0][i];
}
for(int i=3;i>=0;i--)
{
str+=g[1][i];
}
return str;
}
string opA(string str)
{
toM(str);
for(int i=0;i<4;i++)
{
swap(g[0][i],g[1][i]);
}
return getStr();
}
string opB(string str)
{
toM(str);
char v0=g[0][3],v1=g[1][3];
for(int i=2;i>=0;i--)
{
g[0][i+1]=g[0][i];
g[1][i+1]=g[1][i];
}
g[0][0]=v0,g[1][0]=v1;
return getStr();
}
string opC(string str)
{
toM(str);
char v=g[0][1];
g[0][1]=g[1][1];
g[1][1]=g[1][2];
g[1][2]=g[0][2];
g[0][2]=v;
return getStr();
}
void bfs(string st)
{
if(st==ed)
return;
queue<string> q;
q.push(st);
dis[st]=0;
while(!q.empty())
{
string top=q.front();
q.pop();
string tmp[3];
tmp[0]=opA(top);
tmp[1]=opB(top);
tmp[2]=opC(top);
for(int i=0;i<3;i++)
{
if(dis.count(tmp[i])==0)
{
dis[tmp[i]]=dis[top]+1;
pre[tmp[i]]=make_pair(i+'A',top);
q.push(tmp[i]);
if(tmp[i]==ed)
return;
}
}
}
}
int main()
{
for(int i=0;i<4;i++)
{
g[0][i]='1'+i;
st+=g[0][i];
}
for(int i=3,j=5;i>=0;i--,j++)
{
g[1][i]='0'+j;
st+=g[1][i];
}
for(int i=0;i<8;i++)
{
char c;
cin>>c;
ed+=c;
}
bfs(st);
cout<<dis[ed]<<endl;
string op="";
while(st!=ed)
{
op+=pre[ed].first;
ed=pre[ed].second;
}
reverse(op.begin(),op.end());
if(op.length()!=0)
cout<<op<<endl;
return 0;
}
2.5 双端队列广搜
2.5.1 175. 电路维修
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=510;
int T;
int r,c;
char g[N][N];
int dis[N][N];
bool st[N][N];
struct Node{
int x,y;
}node;
bool judge(int x,int y)
{
if(x>r||x<0||y>c||y<0)
{
return false;
}
return true;
}
int bfs()
{
int X[]={-1,-1,1,1},Y[]={-1,1,1,-1};
int ix[]={-1,-1,0,0},iy[]={-1,0,0,-1};
char cs[]="\\/\\/";
fill(dis[0],dis[0]+N*N,1e9);
fill(st[0],st[0]+N*N,false);
deque<Node> q;
node.x=0,node.y=0;
dis[0][0]=0;
q.push_back(node);
while(!q.empty())
{
Node top=q.front();
q.pop_front();
if(st[top.x][top.y]) continue;
st[top.x][top.y]=true;
for(int i=0;i<4;i++)
{
int newX=top.x+X[i],newY=top.y+Y[i];
if(judge(newX,newY))
{
int cx=top.x+ix[i],cy=top.y+iy[i];
int d=dis[top.x][top.y]+(g[cx][cy]!=cs[i]);
if(d<dis[newX][newY])
{
dis[newX][newY]=d;
node.x=newX,node.y=newY;
if(g[cx][cy]!=cs[i])
{
q.push_back(node);
}
else q.push_front(node);
}
}
}
}
return dis[r][c];
}
int main()
{
cin>>T;
while(T--)
{
cin>>r>>c;
for(int i=0;i<r;i++)
{
cin>>g[i];
}
int ans=bfs();
if(ans==1e9)
cout<<"NO SOLUTION"<<endl;
else
cout<<ans<<endl;
}
return 0;
}
2.6 双向广搜
2.6.1 190. 字串变换
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=10;
int n;
string A,B;
string a[N],b[N];
int extend(queue<string> &q,map<string,int> &ha,map<string,int> &hb,string a[],string b[])
{
int tmp=ha[q.front()];
while(!q.empty()&&tmp==ha[q.front()])
{
string t=q.front();
q.pop();
for(int i=0;i<n;i++)
{
for(int j=0;j<t.length();j++)
{
if(t.substr(j,a[i].length())==a[i])
{
string r=t;
r.replace(j,a[i].length(),b[i]);
if(hb.count(r)) return ha[t]+hb[r]+1;
if(ha.count(r)) continue;
ha[r]=ha[t]+1;
q.push(r);
}
}
}
}
return 11;
}
int bfs()
{
queue<string> qa,qb;
map<string,int> ha,hb;
ha[A]=0,hb[B]=0;
qa.push(A);
qb.push(B);
int step=0;
while((!qa.empty())&&(!qb.empty()))
{
int t;
if(qa.size()<qb.size()) t=extend(qa,ha,hb,a,b);
else t=extend(qb,hb,ha,b,a);
if(t<=10)
return t;
if(++step==10) return -1;
}
return -1;
}
int main()
{
cin>>A>>B;
string x,y;
while(cin>>x>>y)
{
a[n]=x,b[n]=y,n++;
}
int ans=bfs();
if(ans==-1)
cout<<"NO ANSWER!";
else
cout<<ans;
return 0;
}
2.7 A*
2.7.1 178. 第K短路
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1010,E=200010;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
int n,m;
int S,T,K;
int h[N],rh[N],e[E],w[E],ne[E],idx;
int dist[N],f[N],cnt[N];
bool st[N];
void add(int h[],int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void djk()
{
fill(dist,dist+N,1e9);
dist[T]=0;
priority_queue<PII,vector<PII>,greater<PII> >heap;
heap.push(make_pair(0,T));
while(heap.size())
{
PII t=heap.top();
heap.pop();
int ver=t.second;
if(st[ver]) continue;
st[ver]=true;
for(int i=rh[ver];i!=-1;i=ne[i])
{
int j=e[i];
if(dist[j]>dist[ver]+w[i])
{
dist[j]=dist[ver]+w[i];
heap.push(make_pair(dist[j],j));
}
}
}
for(int i=0;i<n;i++)
f[i]=dist[i];
}
int a_star()
{
priority_queue<PIII,vector<PIII>,greater<PIII> > heap;
heap.push(make_pair(dist[S],make_pair(0,S)));
while(heap.size())
{
PIII t=heap.top();
heap.pop();
int ver=t.second.second,distance=t.second.first;
cnt[ver]++;
if(cnt[T]==K) return distance;
for(int i=h[ver];i!=-1;i=ne[i])
{
int j=e[i];
if(cnt[j]<K)
{
heap.push(make_pair(distance+w[i]+f[j],make_pair(distance+w[i],j)));
}
}
}
return -1;
}
int main()
{
cin>>n>>m;
fill(h,h+N,-1);
fill(rh,rh+N,-1);
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
add(h,a,b,c),add(rh,b,a,c);
}
cin>>S>>T>>K;
if(S==T) K+=1;
djk();
cout<<a_star();
return 0;
}
2.7.2 179. 八数码
代码:
#include<bits/stdc++.h>
using namespace std;
char g[3][3];
string a,b="12345678x";
unordered_map<string,pair<char,string> > pre;
void toG(string s)
{
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
g[i][j]=s[i*3+j];
}
}
}
string toS()
{
string s="";
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
s+=g[i][j];
}
}
return s;
}
void getXY(int &x,int &y)
{
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
if(g[i][j]=='x')
{
x=i,y=j;
return;
}
}
}
}
string opU(string s)
{
toG(s);
int x,y;
getXY(x,y);
if(x!=0)
{
swap(g[x][y],g[x-1][y]);
return toS();
}
else return "";
}
string opD(string s)
{
toG(s);
int x,y;
getXY(x,y);
if(x!=2)
{
swap(g[x][y],g[x+1][y]);
return toS();
}
else return "";
}
string opL(string s)
{
toG(s);
int x,y;
getXY(x,y);
if(y!=0)
{
swap(g[x][y],g[x][y-1]);
return toS();
}
else return "";
}
string opR(string s)
{
toG(s);
int x,y;
getXY(x,y);
if(y!=2)
{
swap(g[x][y],g[x][y+1]);
return toS();
}
else return "";
}
int bfs()
{
if(a==b)
return 0;
queue<string> q;
q.push(a);
pre[a]=make_pair('*',"");
map<int,char> op;
op[0]='u';
op[1]='d';
op[2]='l';
op[3]='r';
while(q.size())
{
string t=q.front();
q.pop();
string tmp[4];
tmp[0]=opU(t);
tmp[1]=opD(t);
tmp[2]=opL(t);
tmp[3]=opR(t);
for(int i=0;i<4;i++)
{
if(tmp[i]!=""&&pre.count(tmp[i])==0)
{
q.push(tmp[i]);
pre[tmp[i]]=make_pair(op[i],t);
if(tmp[i]==b)
return 1;
}
}
}
return -1;
}
int main()
{
for(int i=0;i<9;i++)
{
char c;
cin>>c;
a+=c;
}
int t=bfs();
if(t==-1)
cout<<"unsolvable";
else
{
string ans="";
string tmp=b;
while(tmp!=a)
{
ans+=pre[tmp].first;
tmp=pre[tmp].second;
}
reverse(ans.begin(),ans.end());
cout<<ans;
}
return 0;
}
//2 3 4 1 5 x 7 6 8
2.8 DFS之连通性模型
2.8.1 1112. 迷宫
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int k,n;
char g[N][N];
int sx,sy,ex,ey;
bool st[N][N];
int X[]={1,-1,0,0},Y[]={0,0,1,-1};
bool judge(int x,int y)
{
if(x>=n||x<0||y>=n||y<0)
return false;
if(g[x][y]=='#'||st[x][y]==true)
return false;
return true;
}
bool dfs(int x,int y)
{
if(g[x][y]=='#')
return false;
if(x==ex&&y==ey)
return true;
st[x][y]=true;
for(int i=0;i<4;i++)
{
int newX=x+X[i],newY=y+Y[i];
if(judge(newX,newY))
{
if(dfs(newX,newY)) return true;
}
}
return false;
}
int main()
{
cin>>k;
while(k--)
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>g[i];
}
cin>>sx>>sy>>ex>>ey;
fill(st[0],st[0]+N*N,false);
if(sx==ex&&sy==ey&&g[ex][ey]!='#')
cout<<"YES"<<endl;
else if(g[sx][sy]=='#'||g[ex][ey]=='#')
{
cout<<"NO"<<endl;
}
else
{
bool flag=dfs(sx,sy);
if(flag)
cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
return 0;
}
/* BFS
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int k,n;
char g[N][N];
int sx,sy,ex,ey;
bool st[N][N];
int X[]={1,-1,0,0},Y[]={0,0,1,-1};
struct Node{
int x,y;
}node;
bool judge(int x,int y)
{
if(x>=n||x<0||y>=n||y<0)
return false;
if(g[x][y]=='#'||st[x][y]==true)
return false;
return true;
}
bool bfs()
{
if(g[sx][sy]=='#'||g[ex][ey]=='#')
return false;
fill(st[0],st[0]+N*N,false);
queue<Node> q;
node.x=sx,node.y=sy;
q.push(node);
st[sx][sy]=true;
while(q.size())
{
Node t=q.front();
q.pop();
for(int i=0;i<4;i++)
{
int newX=t.x+X[i],newY=t.y+Y[i];
if(judge(newX,newY))
{
node.x=newX,node.y=newY;
q.push(node);
st[newX][newY]=true;
if(ex==newX&&ey==newY)
return true;
}
}
}
return false;
}
int main()
{
cin>>k;
while(k--)
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>g[i];
}
cin>>sx>>sy>>ex>>ey;
if(sx==ex&&sy==ey&&g[ex][ey]!='#')
cout<<"YES"<<endl;
else
{
bool flag=bfs();
if(flag)
cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
return 0;
}
*/
2.8.2 1113. 红与黑
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=30;
char g[N][N];
int ans;
int n,m;
int sx,sy;
int X[]={0,0,1,-1},Y[]={1,-1,0,0};
bool st[N][N];
bool judge(int x,int y)
{
if(x>=n||x<0||y>=m||y<0)
return false;
if(st[x][y]==true||g[x][y]=='#')
return false;
return true;
}
void dfs(int x,int y)
{
if(st[x][y]) return;
st[x][y]=true;
ans++;
for(int i=0;i<4;i++)
{
int newX=x+X[i],newY=y+Y[i];
if(judge(newX,newY))
{
dfs(newX,newY);
}
}
return;
}
int main()
{
while(true)
{
cin>>m>>n;
if(m==n&&n==0)
break;
for(int i=0;i<n;i++)
{
cin>>g[i];
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(g[i][j]=='@')
{
sx=i,sy=j;
}
}
}
ans=0;
fill(st[0],st[0]+N*N,false);
dfs(sx,sy);
cout<<ans<<endl;
}
return 0;
}
2.9 DFS之搜索顺序
2.9.1 1116. 马走日
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=10;
int n,m,x,y;
bool st[N][N];
int ans;
int X[]={-1,1,-2,2,-2,2,-1,1},Y[]={-2,-2,-1,-1,1,1,2,2};
void dfs(int x,int y,int cnt)
{
if(cnt==n*m)
{
ans++;
return;
}
st[x][y]=true;
for(int i=0;i<8;i++)
{
int newX=x+X[i],newY=y+Y[i];
if(newX>=n||newX<0||newY>=m||newY<0) continue;
if(st[newX][newY]) continue;
dfs(newX,newY,cnt+1);
}
st[x][y]=false;
}
int main()
{
std::ios::sync_with_stdio(0);
int T;
cin>>T;
while(T--)
{
cin>>n>>m>>x>>y;
ans=0;
dfs(x,y,1);
cout<<ans<<endl;
}
return 0;
}
2.9.2 1117. 单词接龙
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=50;
string str[N],start;
int n;
bool st[N];
int ans;
bool judge(string s)
{
for(int i=0;i<2*n;i++)
{
int _min=min(s.length(),str[i].length());
for(int len=1;len<_min;len++)
{
if(s.substr(s.length()-len)==str[i].substr(0,len)&&st[i]==false)
{
return true;
}
}
}
return false;
}
void dfs(string s)
{
if(judge(s))
{
string tmp="";
for(int i=0;i<2*n;i++)
{
int _min=min(s.length(),str[i].length());
for(int len=1;len<_min;len++)
{
if(s.substr(s.length()-len)==str[i].substr(0,len)&&st[i]==false)
{
st[i]=true;
tmp=s+str[i].substr(len);
dfs(tmp);
st[i]=false;
}
}
}
}
else
{
ans=max(ans,(int)s.length());
return;
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++) cin>>str[i];
for(int i=n;i<2*n;i++) str[i]=str[i-n];
cin>>start;
string s="#"+start;
dfs(s);
cout<<ans-1<<endl;
return 0;
}
2.9.3 1118. 分成互质组
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=11;
int n;
int p[N];
int group[N][N];
bool st[N];
int ans=N;
//g:第几组;gc:当前组内下标是什么;
//tc:当前组中共有多少元素;start:当前组可以从哪个下标开始搜
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
bool check(int group[],int gc,int i)
{
for(int j=0;j<gc;j++)
{
if(gcd(p[group[j]],p[i])>1)
return false;
}
return true;
}
void dfs(int g,int gc,int tc,int start)
{
if(g>=ans) return;
if(tc==n) ans=g;
bool flag=true;
for(int i=start;i<n;i++)
{
if(!st[i]&&check(group[g],gc,i))
{
st[i]=true;
group[g][gc]=i;
dfs(g,gc+1,tc+1,i+1);
st[i]=false;
flag=false;
}
}
if(flag) dfs(g+1,0,tc,0);
}
int main()
{
cin>>n;
for(int i=0;i<n;i++) cin>>p[i];
dfs(1,0,0,0);
cout<<ans;
return 0;
}
2.10 DFS之剪枝与优化
2.10.1 165. 小猫爬山
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=25;
int n,w;
int cat[N];
int sum[N];
bool st[N];
int ans=N;
bool cmp(int a,int b)
{
return a>b;
}
void dfs(int u,int k)
{
if(k>=ans) return;
if(u==n)
{
ans=k;
return;
}
for(int i=0;i<k;i++)
{
if(cat[u]+sum[i]<=w)
{
sum[i]+=cat[u];
dfs(u+1,k);
sum[i]-=cat[u];
}
}
sum[k]=cat[u];
dfs(u+1,k+1);
sum[k]=0;
}
int main()
{
cin>>n>>w;
for(int i=0;i<n;i++) cin>>cat[i];
sort(cat,cat+n,cmp);
dfs(0,0);
cout<<ans;
return 0;
}
2.10.2 166. 数独
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=9;
char str[100];
int ones[1<<N],mp[1<<N];
int row[N],col[N],cell[3][3];
inline int lowbit(int x)
{
return x&-x;
}
void init()
{
for(int i=0;i<N;i++)
{
row[i]=(1<<N)-1;
col[i]=(1<<N)-1;
}
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
cell[i][j]=(1<<N)-1;
}
}
}
inline int get(int x,int y)
{
return row[x]&col[y]&cell[x/3][y/3];
}
bool bfs(int cnt)
{
if(cnt==0) return true;
int x,y,minv=10;
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
if(str[i*N+j]=='.')
{
int t=ones[get(i,j)];
if(t<minv)
{
x=i,y=j,minv=t;
}
}
}
}
int t=get(x,y);
for(;t!=0;t-=lowbit(t))
{
int n=mp[lowbit(t)];
row[x]-=1<<n;
col[y]-=1<<n;
cell[x/3][y/3]-=1<<n;
str[x*N+y]='1'+n;
if(bfs(cnt-1)) return true;
row[x]+=1<<n;
col[y]+=1<<n;
cell[x/3][y/3]+=1<<n;
str[x*N+y]='.';
}
return false;
}
int main()
{
for(int i=0;i<N;i++) mp[1<<i]=i;
for(int i=0;i<(1<<N);i++)
{
int s=0;
for(int j=i;j;j-=lowbit(j)) s++;
ones[i]=s;
}
while(true)
{
init();
cin>>str;
if(str[0]=='e')
break;
int cnt=0;
for(int i=0,k=0;i<N;i++)
{
for(int j=0;j<N;j++,k++)
{
if(str[k]!='.')
{
int t=str[k]-'1';
row[i]-=1<<t;
col[j]-=1<<t;
cell[i/3][j/3]-=1<<t;
}
else cnt++;
}
}
bfs(cnt);
cout<<str<<endl;
}
return 0;
}
2.10.3 167. 木棒
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=70;
int sticks[N];
bool st[N];
int n;
int sum,length;
bool dfs(int u,int cur,int start)
{
if(u*length==sum) return true;
if(cur==length) return dfs(u+1,0,0);
for(int i=start;i<n;i++)
{
int l=sticks[i];
if(st[i]||cur+l>length) continue;
st[i]=true;
if(dfs(u,cur+l,i+1)) return true;
st[i]=false;
if(!cur||cur+l==length) return false;
int j=i;
while(j<n&&sticks[j]==sticks[i]) j++;
i=j-1;
}
return false;
}
int main()
{
while(true)
{
fill(st,st+N,false);
sum=0,length=0;
cin>>n;
if(n==0) break;
for(int i=0;i<n;i++)
{
cin>>sticks[i];
sum+=sticks[i];
length=max(length,sticks[i]);
}
sort(sticks,sticks+n);
reverse(sticks,sticks+n);
while(length<=sum)
{
if(sum%length==0&&dfs(0,0,0))
{
cout<<length<<endl;
break;
}
length++;
}
}
return 0;
}
2.10.4 168. 生日蛋糕
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=25,INF=1e9;
int n,m;
int minv[N],mins[N];
int R[N],H[N];
int ans=INF;
void dfs(int u,int v,int s)
{
if(v+minv[u]>n) return;
if(s+mins[u]>=ans) return;
if(s+2*(n-v)/R[u+1]>=ans) return;
if(!u)
{
if(v==n) ans=s;
return;
}
for(int r=min(R[u+1]-1,(int)sqrt(n-v));r>=u;r--)
{
for(int h=min(H[u+1]-1,(n-v)/r/r);h>=u;h--)
{
int t=0;
if(u==m) t=r*r;
R[u]=r,H[u]=h;
dfs(u-1,v+r*r*h,s+2*r*h+t);
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
minv[i]=minv[i-1]+i*i*i;
mins[i]=mins[i-1]+2*i*i;
}
R[m+1]=H[m+1]=INF;
dfs(m,0,0);
if(ans==INF) cout<<0<<endl;
else cout<<ans<<endl;
return 0;
}
2.11 迭代加深
2.11.1 170. 加成序列
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int n;
int path[N];
bool dfs(int u,int depth)
{
if(u==depth) return path[u-1]==n;
bool st[N]={false};
for(int i=u-1;i>=0;i--)
{
for(int j=i;j>=0;j--)
{
int s=path[i]+path[j];
if(s>path[u-1]&&s<=n&&!st[s])
{
st[s]=true;
path[u]=s;
if(dfs(u+1,depth)) return true;
}
}
}
return false;
}
int main()
{
while(true)
{
cin>>n;
if(n==0) break;
int depth=1;
path[0]=1;
while(!dfs(1,depth)) depth++;
for(int i=0;i<depth;i++)
{
cout<<path[i]<<" ";
}
cout<<endl;
}
return 0;
}
2.12 双向DFS
2.12.1 171. 送礼物
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=50;
typedef long long LL;
int n,m,k;
int g[N];
int weights[1<<24],cnt;
int ans;
void dfs_1(int u,int s)
{
if(u==k)
{
weights[cnt++]=s;
return;
}
if((LL)s+g[u]<=m) dfs_1(u+1,s+g[u]);
dfs_1(u+1,s);
}
void dfs_2(int u,int s)
{
if(u==n)
{
int l=0,r=cnt-1;
while(l<r)
{
int mid=l+r+1>>1;
if((LL)weights[mid]+s<=m) l=mid;
else r=mid-1;
}
if(weights[r]+s<=m)
ans=max(ans,weights[r]+s);
return;
}
if((LL)s+g[u]<=m) dfs_2(u+1,s+g[u]);
dfs_2(u+1,s);
}
int main()
{
cin>>m>>n;
for(int i=0;i<n;i++) cin>>g[i];
sort(g,g+n);
reverse(g,g+n);
k=n/2+2;
dfs_1(0,0);
sort(weights,weights+cnt);
cnt=unique(weights,weights+cnt)-weights;
dfs_2(k,0);
cout<<ans;
return 0;
}
2.13 IDA*
2.13.1 180. 排书
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=15;
int n;
int q[N];
int w[5][N];
int f()
{
int tot=0;
for(int i=0;i+1<n;i++)
{
if(q[i+1]!=q[i]+1)
tot++;
}
return (tot+2)/3;
}
bool check()
{
for(int i=0;i<n;i++)
{
if(q[i]!=i+1)
return false;
}
return true;
}
bool dfs(int depth,int max_depth)
{
if(depth+f()>max_depth) return false;
if(check()) return true;
for(int len=1;len<=n;len++)
{
for(int l=0;l+len-1<n;l++)
{
int r=l+len-1;
for(int k=r+1;k<n;k++)
{
memcpy(w[depth],q,sizeof q);
int x,y;
for(x=r+1,y=l;x<=k;x++,y++)
{
q[y]=w[depth][x];
}
for(x=l;x<=r;x++,y++)
{
q[y]=w[depth][x];
}
if(dfs(depth+1,max_depth)) return true;
memcpy(q,w[depth],sizeof q);
}
}
}
return false;
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n;
for(int i=0;i<n;i++)
cin>>q[i];
int depth=0;
while(depth<5&&!dfs(0,depth)) depth++;
if(depth>=5) cout<<"5 or more"<<endl;
else cout<<depth<<endl;
}
return 0;
}
2.13.2 181. 回转游戏
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=24;
int op[8][7]={
{0,2,6,11,15,20,22},
{1,3,8,12,17,21,23},
{10,9,8,7,6,5,4},
{19,18,17,16,15,14,13},
{23,21,17,12,8,3,1},
{22,20,15,11,6,2,0},
{13,14,15,16,17,18,19},
{4,5,6,7,8,9,10}
};
int oppsite[8]={5,4,7,6,1,0,3,2};
int center[8]={6,7,8,11,12,15,16,17};
int q[N];
int path[100];
int sum[4];
int f()
{
fill(sum,sum+4,0);
for(int i=0;i<8;i++)
sum[q[center[i]]]++;
int k=0;
for(int i=1;i<=3;i++)
{
k=max(k,sum[i]);
}
return 8-k;
}
void operate(int x)
{
int t=q[op[x][0]];
for(int i=1;i<7;i++)
{
q[op[x][i-1]]=q[op[x][i]];
}
q[op[x][6]]=t;
}
bool dfs(int depth,int max_depth,int last)
{
if(depth+f()>max_depth) return false;
if(f()==0) return true;
for(int i=0;i<8;i++)
{
if(oppsite[i]==last) continue;
operate(i);
path[depth]=i;
if(dfs(depth+1,max_depth,i)) return true;
operate(oppsite[i]);
}
return false;
}
int main()
{
while(scanf("%d",&q[0]),q[0])
{
for(int i=1;i<N;i++)
{
scanf("%d",&q[i]);
}
int depth=0;
while(!dfs(0,depth,-1)) depth++;
if(!depth)
puts("No moves needed");
else
{
for(int i=0;i<depth;i++)
{
printf("%c",path[i]+'A');
}
puts("");
}
printf("%d\n",q[6]);
}
return 0;
}