專題連接:https://cn.vjudge.net/contest/65959
A - 棋盤問題
題意:在棋盤上放k個棋子的方案數。要求每行每列至多隻有一個。
思路:DFS。詳見代碼。
#include <cstdio> using namespace std; char m[10][10]; int n,k; int ans; void dfs(int x,int y,int num) { if(num==k) { ans++; return; } while(x<=n) { if(m[x][y]=='#') { int flag=1; for(int j=1;j<=n;j++) if(m[j][y]=='*'||m[x][j]=='*') flag=0; if(flag==1) { m[x][y]='*'; dfs(x,y,num+1); m[x][y]='#'; } } y++; if(y>n) { y=1; x++; } } } int main() { while(~scanf("%d%d",&n,&k)) { if(n==-1&&k==-1) break; for(int i=1;i<=n;i++) scanf("%s",m[i]+1); ans=0; dfs(1,1,0); printf("%d\n",ans); } return 0; }
B - Dungeon Master
題意:三維走迷宮問題。
思路:BFS,注意邊界判斷,詳見代碼。
#include <cstdio> #include <queue> #include <cstring> #include <iostream> using namespace std; const int INF=0x3f3f3f3f; char m[40][40][40]; bool use[40][40][40]; int dirx[6]={0,0,0,0,1,-1}; int diry[6]={0,0,1,-1,0,0}; int dirz[6]={1,-1,0,0,0,0}; int l,r,c,ans; struct node { int x;//r int y;//c int z;//l int num; }s,t; void bfs() { queue<node >q; q.push(s); while(!q.empty()) { node now=q.front(); q.pop(); use[now.x][now.y][now.z]=1; if(now.x==t.x&&now.y==t.y&&now.z==t.z) ans=min(ans,now.num); else for(int i=0;i<6;i++) { if(now.x+dirx[i]<1||now.x+dirx[i]>r) continue; if(now.y+diry[i]<1||now.y+diry[i]>c) continue; if(now.z+dirz[i]<1||now.z+dirz[i]>l) continue; node next; next.x=now.x+dirx[i]; next.y=now.y+diry[i]; next.z=now.z+dirz[i]; next.num=now.num+1; if(m[next.x][next.y][next.z]!='#'&&use[next.x][next.y][next.z]==0) { q.push(next); use[next.x][next.y][next.z]=1; } } } } int main() { while(scanf("%d%d%d",&l,&r,&c)!=EOF) { if(l==0&&r==0&&c==0) break; for(int i=1;i<=l;i++) { for(int j=1;j<=r;j++) { getchar(); for(int k=1;k<=c;k++) { scanf("%c",&m[j][k][i]); if(m[j][k][i]=='S') s.x=j,s.y=k,s.z=i,s.num=0; else if(m[j][k][i]=='E') t.x=j,t.y=k,t.z=i; } } getchar(); } memset(use,0,sizeof(use)); ans=INF; bfs(); if(ans==INF) printf("Trapped!\n"); else printf("Escaped in %d minute(s).\n",ans); } return 0; }B
C - Catch That Cow
題意:一維數軸上從n點到k的最短用時。三種移動操做:n+1,n-1,n*2.
思路:BFS問題,從起點開始三個方向進行搜索,注意邊界判斷,具體看代碼。
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> using namespace std; const int INF=0x3f3f3f3f; int use[200100]; struct node { int x; int num; }; int ans; int n,k; int bfs(int nows) { use[nows]=1; queue<node>q; while(!q.empty()) q.pop(); node s; s.x=nows,s.num=0; q.push(s); while(!q.empty()) { node now=q.front(); q.pop(); if(now.x==k) return now.num; if(now.x+1<=100000&&use[now.x+1]==0) { use[now.x+1]=1; node next; next.num=now.num+1; next.x=now.x+1; q.push(next); } if(now.x-1>=0&&now.x-1<=100000&&use[now.x-1]==0) { use[now.x-1]=1; node next; next.num=now.num+1; next.x=now.x-1; q.push(next); } if(now.x*2>=0&&now.x*2<=100000&&use[now.x*2]==0) { use[now.x*2]=1; node next; next.num = now.num + 1; next.x = now.x * 2; q.push(next); } } } int main() { while(~scanf("%d%d",&n,&k)) { memset(use,0,sizeof(use)); ans=bfs(n); printf("%d\n",ans); } return 0; }
D - Fliptile
題意:一個M×N的棋盤,0表示白色,1表示黑色,每次翻轉一個棋子及其相鄰的棋子。問可否將棋盤翻轉爲全白。若是能夠輸出翻轉矩陣。
思路:枚舉第一行的翻轉狀況。由於N<=15。最多有2^15次種狀況。對每種狀況進行搜索,先翻轉第一行棋子,而後遍歷第二行開始的全部棋子,當前棋子上面的棋子若爲黑,則必須翻轉當前棋子。
最後判斷最後一行是否全白。記錄翻轉最小次數。具體看代碼。
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <set> using namespace std; const int INF=0x3f3f3f3f; int m,n; int dirx[4]={0,0,-1,1}; int diry[4]={1,-1,0,0}; int mp[20][20]; int lsmp[20][20]; int ans[20][20]; int lsans[20][20]; int num,lsnum; void f(int x,int y) { lsans[x][y]=1; lsmp[x][y]=1-lsmp[x][y]; for(int i=0;i<4;i++) if(x+dirx[i]>=1&&x+dirx[i]<=m&&y+diry[i]>=1&&y+diry[i]<=n) lsmp[x+dirx[i]][y+diry[i]]=1-lsmp[x+dirx[i]][y+diry[i]]; } void dfs() { lsnum=0; for(int i=1;i<=n;i++) if(lsans[1][i]==1) { f(1,i); lsnum++; } for(int i=2;i<=m;i++) for(int j=1;j<=n;j++) if(lsmp[i-1][j]==1) { f(i,j); lsnum++; } int flag=1; for(int j=1;j<=n;j++) if(lsmp[m][j]==1) flag=0; if(flag==1) { if(lsnum<num) { num=lsnum; for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) ans[i][j]=lsans[i][j]; } } } int main() { while(cin>>m>>n) { for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) scanf("%d",&mp[i][j]); num=INF; for(int k=0;k<(1<<(n));k++) { memset(lsans,0, sizeof(lsans)); for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) lsmp[i][j]=mp[i][j]; for(int j=1;j<=n;j++) { if(k&(1<<(j-1))) lsans[1][j]=1; } dfs(); } if(num==INF) printf("IMPOSSIBLE\n"); else { for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) if (j != n) printf("%d ", ans[i][j]); else printf("%d\n", ans[i][j]); } } } }
E - Find The Multiple
題意:中文題,很少說。
思路:首先注意到全部m確定是一個小的m×10或者m×10+1獲得的。那麼咱們能夠從n開始枚舉m,直到找到知足要求(m%n==0)的解。實際上最大的m也不會超過long long 。具體看代碼。
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <set> using namespace std; typedef long long int ll; const int INF=0x3f3f3f3f; int n; void bfs() { queue<ll> q; q.push(1); while(!q.empty()) { ll now=q.front(); q.pop(); if(now%n==0) { cout<<now<<endl; return ; } q.push(now*10); q.push(now*10+1); } } int main() { while(scanf("%d",&n)&&n) { bfs(); } return 0; }
F - Prime Path
題意:給出四位數的質數n,m。要求每次變換某一位上的數字且每次變換後的數也是質數,求從n到m的最小變換次數。
思路:n和m都只有四位,預處理出質數,直接BFS便可。具體看代碼。
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <set> using namespace std; const int INF=0x3f3f3f3f; bool flag[10010]; bool visit[10010]; int t,n,m; struct node { int x; int step; }; void init() { flag[0]=flag[1]=1; for(int i=2;i<=10000;i++) if(flag[i]==0) { for(int j=i*2;j<=10000;j+=i) flag[j]=1; } } int power(int x,int t) { int ans=1; for(int i=1;i<=t;i++) ans*=x; return ans; } void bfs(int n,int m) { memset(visit,0, sizeof(visit)); node now; visit[n]=1; now.x=n,now.step=0; queue<node>q; q.push(now); while(!q.empty()) { node temp=q.front();q.pop(); if(temp.x==m) { printf("%d\n",temp.step); return ; } int num[5]; int nowx=temp.x; num[4]=nowx%10;nowx/=10; num[3]=nowx%10;nowx/=10; num[2]=nowx%10;nowx/=10; num[1]=nowx%10;nowx/=10; for(int i=1;i<=4;i++) for(int j=0;j<=9;j++) { if(i==1&&j==0) continue; if(num[i]==j) continue; if(i==4&&j==0) continue; int nown=temp.x; nown=nown-num[i]*power(10,4-i)+j*power(10,4-i); if(flag[nown]==0&&visit[nown]==0) { visit[nown]=1; node next; next.x=nown; next.step=temp.step+1; q.push(next); } } } printf("Impossible\n"); } int main() { init(); cin>>t; while(t--) { cin>>n>>m; if(n==m) cout<<"0"<<endl; else bfs(n,m); } }
G - Shuffle'm Up
題意:給出字符串長度C,兩個長度爲C的字符串a,b 一個長度爲2C的字符串c。每次操做依次輪流從b和a取出字符組成新的字符串d。若是d!=c,將d前半部分給a,後半部分給把,問須要幾回操做能夠獲得C。若是不能輸出-1。
思路:雖然放在搜索裏,實際上是個模擬吧。照着作就好了。注意若是操做次數超過了2C就永遠不能組成了。具體看代碼。
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <string> using namespace std; const int INF=0x3f3f3f3f; bool flag[10010]; bool visit[10010]; int T,C; string a,b,c; int main() { cin>>T; int cases=1; while(T--) { cin>>C; cin>>a>>b>>c; if(a+b==c) printf("%d 0\n",cases++); else { int num=0; int flag=0; while(num<=2*C) { num++; string d=""; for(int i=0;i<C;i++) d=d+b[i]+a[i]; if(d==c) { flag=1;break; } a=""; for(int i=0;i<C;i++) a+=d[i]; b=""; for(int i=0;i<C;i++) b+=d[C+i]; } if(flag==0) printf("%d -1\n",cases++); else printf("%d %d\n",cases++,num); } } }
H - Pots
題意:有容量爲a,b兩個容器,問可否經過三種操做(倒滿某個容器,倒空某個容器,將一個容器的水倒入另外一個容器)獲得容量C。輸出最小操做數和操做過程或者impossible。
思路:由於a,b<100,直接6方向BFS便可。能夠將操做過程在BFS過程同時更新。具體看代碼。
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <string> using namespace std; const int INF=0x3f3f3f3f; bool use[110][110]; int aa,bb,cc; struct caozuo { int num; int from; int to; }; struct node { int a; int b; int step; vector<caozuo> v; }; void bfs() { //temlist.assign(list.begin(), list.end()); node now; now.a=0; now.b=0; memset(use,0, sizeof(use)); use[0][0]=1; now.v.clear(); now.step=0; queue<node >q; q.push(now); while(!q.empty()) { node temp=q.front();q.pop(); if(temp.a==cc||temp.b==cc) { printf("%d\n",temp.step); for(int i=0;i<temp.v.size();i++) { caozuo now=temp.v[i]; if(now.num==1) { if(now.from==1) printf("FILL(1)\n"); else printf("FILL(2)\n"); } else if(now.num==2) { if(now.from==1) printf("DROP(1)\n"); else printf("DROP(2)\n"); } else if(now.num==3) { if(now.from==1) printf("POUR(1,2)\n"); else printf("POUR(2,1)\n"); } } return ; } if(temp.a!=aa&&use[aa][temp.b]==0)//a-fill { use[aa][temp.b]=1; node next; next.a=aa; next.b=temp.b; next.step=temp.step+1; next.v.assign(temp.v.begin(),temp.v.end()); caozuo next1; next1.num=1; next1.from=1; next.v.push_back(next1); q.push(next); } if(temp.b!=bb&&use[temp.a][bb]==0)//b-fill { use[temp.a][bb]=1; node next; next.a=temp.a; next.b=bb; next.step=temp.step+1; next.v.assign(temp.v.begin(),temp.v.end()); caozuo next1; next1.num=1; next1.from=2; next.v.push_back(next1); q.push(next); } if(temp.a!=0&&use[0][temp.b]==0)//a-0 { use[0][temp.b]=1; node next; next.a=0; next.b=temp.b; next.step=temp.step+1; next.v.assign(temp.v.begin(),temp.v.end()); caozuo next1; next1.num=2; next1.from=1; next.v.push_back(next1); q.push(next); } if(temp.b!=0&&use[temp.a][0]==0)//b-0 { use[temp.a][0]=1; node next; next.a=temp.a; next.b=0; next.step=temp.step+1; next.v.assign(temp.v.begin(),temp.v.end()); caozuo next1; next1.num=2; next1.from=2; next.v.push_back(next1); q.push(next); } if(temp.a!=0&&temp.b!=bb)//a-b { if(temp.a+temp.b<=bb&&use[0][temp.a+temp.b]==0) { use[0][temp.a+temp.b] = 1; node next; next.a = 0; next.b = temp.a+temp.b; next.step = temp.step + 1; next.v.assign(temp.v.begin(), temp.v.end()); caozuo next1; next1.num=3; next1.from=1; next1.to=2; next.v.push_back(next1); q.push(next); } else if(temp.a+temp.b>bb&&use[temp.a+temp.b-bb][bb]==0) { use[temp.a+temp.b-bb][bb] = 1; node next; next.a = temp.a+temp.b-bb; next.b = bb; next.step = temp.step + 1; next.v.assign(temp.v.begin(), temp.v.end()); caozuo next1; next1.num = 3; next1.from = 1; next1.to=2; next.v.push_back(next1); q.push(next); } } if(temp.b!=0&&temp.a!=aa)//b-a { if(temp.a+temp.b<=aa&&use[temp.a+temp.b][0]==0) { use[temp.a+temp.b][0] = 1; node next; next.a = temp.a+temp.b; next.b = 0; next.step = temp.step + 1; next.v.assign(temp.v.begin(), temp.v.end()); caozuo next1; next1.num=3; next1.from=2; next1.to=1; next.v.push_back(next1); q.push(next); } else if(temp.a+temp.b>aa&&use[aa][temp.a+temp.b-aa]==0) { use[aa][temp.a+temp.b-aa] = 1; node next; next.a = aa; next.b = temp.a+temp.b-aa; next.step = temp.step + 1; next.v.assign(temp.v.begin(), temp.v.end()); caozuo next1; next1.num=3; next1.from=2; next1.to=1; next.v.push_back(next1); q.push(next); } } } printf("impossible\n"); } int main() { while(cin>>aa>>bb>>cc) { bfs(); } }
I - Fire Game(http://acm.fzu.edu.cn/problem.php?pid=2150)
題意:'#'能夠燃燒,'.'不能夠燃燒。選擇兩個#點(能夠重複)放火,每過一秒能夠向四個方向燃燒,問可否所有燒光全部的#,若是能夠給出燒光的最少時間。
思路:注意到數據規模很小,咱們能夠暴力枚舉兩個#點。初始化到達每一個#的時間爲INF。作兩遍BFS,到達每一個#的時間爲兩遍BFS裏短的時間。每一種狀況所需的時間爲全部#的最長到達時間。最後取全部最長時間的最小值。具體看代碼。能夠用雙向BFS優化爲一次BFS。
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <set> using namespace std; const int INF=0x3f3f3f3f; int m,n; int dirx[4]={0,0,-1,1}; int diry[4]={1,-1,0,0}; char mp[15][15]; int lsans[15][15],ans; struct node { int x; int y; int step; }; bool use[15][15]; void bfs(int xx,int yy) { memset(use,0,sizeof(use)); queue<node >q; node now; now.x=xx,now.y=yy,now.step=0; use[xx][yy]=1; q.push(now); while(!q.empty()) { node now=q.front(); lsans[now.x][now.y]=min( lsans[now.x][now.y],now.step); q.pop(); for(int i=0;i<4;i++) { node next; next.x=now.x+dirx[i]; next.y=now.y+diry[i]; next.step=now.step+1; if(use[next.x][next.y]==1) continue; if(next.x>=1&&next.x<=n&&next.y>=1&&next.y<=m) if(mp[next.x][next.y]=='#') { use[next.x][next.y]=1; q.push(next); } } } } int main() { int t; int cas=1; scanf("%d",&t); while(t--) { ans=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%s",mp[i]+1); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(mp[i][j]=='#') ans=INF; for(int i=1;i<=n*m;i++) { int nx=i/m+1,ny=i%m; if(ny==0) nx--,ny=m; if(mp[nx][ny]!='#') continue; for(int j=i;j<=n*m;j++) { int nnx=j/m+1,nny=j%m; if(nny==0) nnx--,nny=m; if(mp[nnx][nny]=='#') { memset(lsans,INF,sizeof(lsans)); bfs(nx,ny); bfs(nnx,nny); int lsnum=0; for(int k=1;k<=n;k++) for(int p=1;p<=m;p++) if(mp[k][p]=='#') lsnum=max(lsnum,lsans[k][p]); ans=min(ans,lsnum); } } } if(ans!=INF) printf("Case %d: %d\n",cas++,ans); else printf("Case %d: -1\n",cas++); } }
J - Fire!
題意:F的位置是火,J的位置是人。詢問人是否能夠逃出迷宮,若是能夠求逃出迷宮的時間。注意起火點不必定只有一個。
思路:先作一次BFS求出每一個點的起火時間,再作一遍BFS判斷可否逃出。具體看代碼。
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <set> using namespace std; const int INF=0x3f3f3f3f; const int MAXN=1010; int n,m; struct node { char p; int fire; int peo; int x; int y; }mp[MAXN][MAXN]; int jx,jy,ans; bool use[1010][1010]; int dirx[4]={0,0,1,-1}; int diry[4]={1,-1,0,0}; void dfs1() { queue<node >q; memset(use,0, sizeof(use)); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if(mp[i][j].p=='F') { mp[i][j].fire=0; q.push(mp[i][j]); } } while(!q.empty()) { node now=q.front(); q.pop(); for(int i=0;i<4;i++) { if(now.x+dirx[i]>=1&&now.x+dirx[i]<=n&&now.y+diry[i]>=1&&now.y+diry[i]<=m) if(use[now.x+dirx[i]][now.y+diry[i]]==0) if(mp[now.x+dirx[i]][now.y+diry[i]].p=='.') { use[now.x+dirx[i]][now.y+diry[i]]=1; mp[now.x+dirx[i]][now.y+diry[i]].fire=now.fire+1; q.push(mp[now.x+dirx[i]][now.y+diry[i]]); } } } } void dfs2() { mp[jx][jy].peo=0; queue<node >q; q.push(mp[jx][jy]); memset(use,0, sizeof(use)); use[jx][jy]=1; while(!q.empty()) { node now=q.front(); q.pop(); if(now.x==0||now.x==n+1||now.y==0||now.y==m+1) ans=min(ans,now.peo); for(int i=0;i<4;i++) { if(now.x+dirx[i]>=0&&now.x+dirx[i]<=n+1&&now.y+diry[i]>=0&&now.y+diry[i]<=m+1) if(use[now.x+dirx[i]][now.y+diry[i]]==0) if(now.x+dirx[i]==0||now.x+dirx[i]==n+1||now.y+diry[i]==0||now.y+diry[i]==m+1||mp[now.x+dirx[i]][now.y+diry[i]].p=='.') if(now.x+dirx[i]==0||now.x+dirx[i]==n+1||now.y+diry[i]==0||now.y+diry[i]==m+1||now.peo+1<mp[now.x+dirx[i]][now.y+diry[i]].fire) { use[now.x+dirx[i]][now.y+diry[i]]=1; mp[now.x+dirx[i]][now.y+diry[i]].peo=now.peo+1; q.push(mp[now.x+dirx[i]][now.y+diry[i]]); } } } } int main() { int t; int cas=1; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { getchar(); for(int j=1;j<=m;j++) { scanf("%c",&mp[i][j].p); if(mp[i][j].p=='J') { jx=i; jy=j; } } } for(int i=0;i<=n+1;i++) for(int j=0;j<=m+1;j++) mp[i][j].x=i,mp[i][j].y=j,mp[i][j].peo=mp[i][j].fire=INF; ans=INF; dfs1(); dfs2(); if(ans!=INF) cout<<ans<<endl; else cout<<"IMPOSSIBLE"<<endl; } }
K - 迷宮問題
題意:5×5的地圖,0能夠走,1不能夠走。求從左上角走到有右下角的惟一最短路徑。要求輸出路徑。
思路:BFS。路徑能夠保存在每一次的狀態裏。具體看代碼。
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <string> using namespace std; const int INF=0x3f3f3f3f; int visit[10][10]; int mp[10][10]; int dirx[4]={0,0,1,-1}; int diry[4]={1,-1,0,0}; struct road { int x; int y; }; struct node { int nx; int ny; vector<road>v; }; void bfs() { node now; road now1; now1.x=1,now1.y=1; now.v.push_back(now1); now.nx=1,now.ny=1; memset(visit,0, sizeof(visit)); visit[1][1]=1; queue<node >q; q.push(now); while(!q.empty()) { node temp=q.front(); q.pop(); if(temp.nx==5&&temp.ny==5) { int num=temp.v.size(); for(int i=0;i<num;i++) { printf("(%d, %d)\n",temp.v[i].x-1,temp.v[i].y-1); } return ; } for(int i=0;i<4;i++) { node next; next.nx=temp.nx+dirx[i]; next.ny=temp.ny+diry[i]; next.v.assign(temp.v.begin(),temp.v.end()); road next1; next1.x=next.nx; next1.y=next.ny; next.v.push_back(next1); if(next.nx>=1&&next.nx<=5&&next.ny>=1&&next.ny<=5) if(visit[next.nx][next.ny]==0&&mp[next.nx][next.ny]==0) { visit[next.nx][next.ny]=1; q.push(next); } } } } int main() { for(int i=1;i<=5;i++) for(int j=1;j<=5;j++) cin>>mp[i][j]; bfs(); }
L - Oil Deposits
題意:求聯通塊數,注意斜對角也算聯通。
思路:DFS 每次選擇'@'點,將與之聯通的設爲'.',DFS的次數就是聯通塊數。
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <set> using namespace std; const int INF=0x3f3f3f3f; const int MAXN=110; int n,m; char mp[MAXN][MAXN]; int dirx[8]={1,-1,0,0,1,1,-1,-1}; int diry[8]={0,0,1,-1,1,-1,1,-1}; int ans; void dfs(int x,int y) { mp[x][y]='*'; for(int i=0;i<8;i++) { int nx=x+dirx[i]; int ny=y+diry[i]; if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&mp[nx][ny]=='@') dfs(nx,ny); } } int main() { while(~scanf("%d%d",&n,&m)) { if(n==0&&m==0) break; for(int i=1;i<=n;i++) { scanf("%s",mp[i]+1); } ans=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(mp[i][j]=='@') { ans++; dfs(i,j); } printf("%d\n",ans); } }
M - 很是可樂(HDOJ1495)
題意:給你一瓶容量爲S的可樂和兩個容量分別爲N、M的杯子。詢問最少能平分可樂的次數。若是不能輸出NO。
思路:能夠當作是一個有六個方向的BFS。六個方向:s->n,s->m,n->s,n->m,n->m,m->n 具體看代碼。
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <set> using namespace std; const int INF=0x3f3f3f3f; int nn,mm,ss; bool use[110][110]; struct node { int n; int m; int s; int t; }; int bfs() { node now; now.n=0,now.m=0,now.s=ss,now.t=0; memset(use,0,sizeof(use)); use[0][0]=1; queue<node>q; q.push(now); while(!q.empty()) { node now=q.front(); q.pop(); if(now.n==ss/2&&now.s==ss/2) return now.t; if(now.n<nn)//s->n { int nextn=nn; int nextm=now.m; int nexts=now.n+now.s-nn; if(use[nextn][nextm]==0) { use[nextn][nextm]=1; node next; next.m=nextm; next.n=nextn; next.s=nexts; next.t=now.t+1; q.push(next); } } if(now.m<mm)//s->m { int nextn=now.n; int nextm=mm; int nexts=now.m+now.s-mm; if(use[nextn][nextm]==0) { use[nextn][nextm]=1; node next; next.m=nextm; next.n=nextn; next.s=nexts; next.t=now.t+1; q.push(next); } } if(now.n>0)//n->s { int nextn=0; int nextm=now.m; int nexts=now.n+now.s; if(use[nextn][nextm]==0) { use[nextn][nextm]=1; node next; next.m=nextm; next.n=nextn; next.s=nexts; next.t=now.t+1; q.push(next); } } if(now.m>0)//m->s { int nextn=now.n; int nextm=0; int nexts=now.m+now.s; if(use[nextn][nextm]==0) { use[nextn][nextm]=1; node next; next.m=nextm; next.n=nextn; next.s=nexts; next.t=now.t+1; q.push(next); } } if(now.m>0&&now.n<nn)//m->n { int nextn,nextm,nexts; if(now.m+now.n<=nn) { nextm=0; nextn=now.m+now.n; nexts=now.s; } else { nextm=now.m+now.n-nn; nextn=nn; nexts=now.s; } if(use[nextn][nextm]==0) { use[nextn][nextm]=1; node next; next.m=nextm; next.n=nextn; next.s=nexts; next.t=now.t+1; q.push(next); } } if(now.n>0&&now.m<mm)//n->m { int nextn,nextm,nexts; if(now.n+now.m<=mm) { nextm=now.m+now.n; nextn=0; nexts=now.s; } else { nextm=mm; nextn=now.n+now.m-mm; nexts=now.s; } if(use[nextn][nextm]==0) { use[nextn][nextm]=1; node next; next.m=nextm; next.n=nextn; next.s=nexts; next.t=now.t+1; q.push(next); } } } return 0; } int main() { while(~scanf("%d%d%d",&ss,&nn,&mm)) { if(nn==0&&mm==0&&ss==0) break; if(nn<mm) swap(nn,mm); if(ss%2==1) printf("NO\n"); else { int ans=bfs(); if(ans==0) printf("NO\n"); else printf("%d\n",ans); } } }
N - Find a way(HDOJ2612)
題意:求兩我的到全部KFC的時間和的最小值。
思路:2次BFS求出兩我的分別到每一個KFC的時間。最後選擇和的最小值。具體看代碼。
#include <cstdio> #include <queue> #include <cstring> #include <iostream> #include <algorithm> #include <set> using namespace std; const int INF=0x3f3f3f3f; int n,m; char mp[210][210]; bool use[210][210]; int ans1[210][210]; int ans2[210][210]; int dirx[4]={0,0,1,-1}; int diry[4]={1,-1,0,0}; struct node { int x; int y; int t; }; void bfs1() { memset(use,0,sizeof(use)); memset(ans1,INF,sizeof(ans1)); node now; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(mp[i][j]=='Y') { now.x=i; now.y=j; break; } now.t=0; use[now.x][now.y]=1; queue<node >q; q.push(now); while(!q.empty()) { node now=q.front(); if(mp[now.x][now.y]=='@') ans1[now.x][now.y]=now.t; q.pop(); for(int i=0;i<4;i++) { node next; next.x=now.x+dirx[i]; next.y=now.y+diry[i]; next.t=now.t+1; if(next.x>=1&&next.x<=n&&next.y>=1&&next.y<=m) if(mp[next.x][next.y]!='#') if(use[next.x][next.y]==0) { use[next.x][next.y]=1; q.push(next); } } } } void bfs2() { memset(use,0, sizeof(use)); memset(ans2,INF,sizeof(ans2)); node now; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(mp[i][j]=='M') { now.x=i; now.y=j; break; } now.t=0; use[now.x][now.y]=1; queue<node >q; q.push(now); while(!q.empty()) { node now=q.front(); if(mp[now.x][now.y]=='@') ans2[now.x][now.y]=now.t; q.pop(); for(int i=0;i<4;i++) { node next; next.x=now.x+dirx[i]; next.y=now.y+diry[i]; next.t=now.t+1; if(next.x>=1&&next.x<=n&&next.y>=1&&next.y<=m) if(mp[next.x][next.y]!='#') if(use[next.x][next.y]==0) { use[next.x][next.y]=1; q.push(next); } } } } void solve() { int ans=INF; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(mp[i][j]=='@') ans=min(ans,ans1[i][j]+ans2[i][j]); printf("%d\n",ans*11); } int main() { while(~scanf("%d%d",&n,&m)) { for(int i=1;i<=n;i++) scanf("%s",mp[i]+1); bfs1(); bfs2(); solve(); } }