T1:棋盘问题 POJ-1321 POJ-1321
分析:本题给出棋盘分布以及落子数目,让我们求出在棋子不同行不同列摆放的情况下,有几种落子方式。
本题我们利用DFS算法,编写一个递归函数。从第一行第一列的位置开始在列内扫描,如果找到合适位置就落子,然后把这一列标记,表示这一列不能够再次落子。
这样之后,将前面落子位置往右往下移一位,在这个新位置调用递归函数。当棋子全部用完,则方案数加1。
PS:要注意理解整个过程的深度优先搜索思路,这样子有利于理解代码。
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 const int maxn=10; 5 char chessboard[maxn][maxn]; 6 bool visit[maxn];//用于标记列是否还能够放下棋子 7 int ans;//表示方案数 8 int k;//表示棋子数目 9 int n;//表示棋盘的大小 10 int DFS(int row,int nums_of_chess){//row代表当前行,nums_of_chess代表已经使用的棋子数目 11 if(nums_of_chess==k){ 12 ans++; 13 return 0; 14 } 15 for(int i=row;i<n;i++) 16 for(int j=0;j<n;j++) 17 if(!visit[j]&&chessboard[i][j]=='#'){//如果这一列没有被标记,而且这个位置是棋盘位置 18 visit[j]=true;//将这一列标记 19 DFS(i+1,nums_of_chess+1);//递归调用函数 20 visit[j]=false;//此处函数已经返回,应该将列标记还原,这样子才能够不影响下一行的过程判定 21 } 22 return 0; 23 } 24 int main(){ 25 while(cin>>n>>k){ 26 if(n==-1&&k==-1) break; 27 memset(visit,false,sizeof(visit)); 28 for(int i=0;i<n;i++) 29 for(int j=0;j<n;j++) 30 cin>>chessboard[i][j]; 31 ans=0; 32 DFS(0,0); 33 cout<<ans<<endl; 34 } 35 return 0; 36 }
T2:迷宫问题 POJ-3984 POJ-3984
问题分析:这是一个迷宫问题,可以理解为最短路线与记录移动路径相结合的问题。最短路线问题一般利用BFS,广度优先搜索的方法来解决。但是这一题还多了一个记录移动路径的要求。
于是构建结构体,代表每一个位置,结构体中包含dir数组则是为了记录每一步的方向。构造BFS函数,返回的是最后一个位置的结构体,通过这个结构体中的dir数组,配合上初始位置的(0,0)坐标
就可以求出每一次移动的坐标,然后输出。
代码如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<cstring> 5 using namespace std; 6 int maze[5][5]; 7 bool visit[5][5]; 8 int dx[4]={1,-1,0,0};//两个数组用于表示移动方向 9 int dy[4]={0,0,1,-1}; 10 struct Node{ 11 int x,y;//表示当前位置的x,y坐标 12 int length;//表示行驶距离 13 int dir[30];//用于记录前面结点移动的方向 14 }; 15 Node &BFS(){ 16 queue<Node> que; 17 Node rec,next; 18 rec.x=0;//初始化起点位置的数据 19 rec.y=0; 20 rec.length=0; 21 que.push(rec); 22 while(que.size()){ 23 rec=que.front(); 24 que.pop(); 25 if(rec.x==4&&rec.y==4) return rec;//到达终点就退出循环 26 for(int i=0;i<4;i++) 27 { 28 int nx=rec.x+dx[i];//表示移动之后的位置 29 int ny=rec.y+dy[i]; 30 if(maze[nx][ny]==0&&nx>=0&&nx<5&&ny>=0&&ny<5&&!visit[nx][ny])//判断当前位置是否满足条件 31 { visit[nx][ny]=true; 32 next=rec;//注意此处next与rec的衔接,这一步是为了记录先前的方向和长度 33 next.x=nx; 34 next.y=ny; 35 next.length=rec.length+1; 36 next.dir[rec.length]=i; 37 que.push(next); 38 } 39 } 40 } 41 } 42 int main(){ 43 for(int i=0;i<5;i++) 44 for(int j=0;j<5;j++) 45 cin>>maze[i][j]; 46 memset(visit,false,sizeof(visit)); 47 Node last=BFS(); 48 printf("(0, 0)\n"); 49 int x=0,y=0; 50 for(int i=0;i<last.length;i++) 51 { 52 53 x+=dx[last.dir[i]]; 54 y+=dy[last.dir[i]]; 55 printf("(%d, %d)\n",x,y); 56 } 57 return 0; 58 }
T3 POJ-2251
问题分析:这是一个迷宫最短路径问题,只不过把以前二维的迷宫变成了三维的迷宫。只要把以前二维的bfs算法延伸到三维即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<cstring> 5 using namespace std; 6 struct Node{ 7 int x,y,z; 8 }; 9 char space[35][35][35]; 10 int dis[35][35][35]; 11 int L,R,C; 12 int sx,sy,sz; 13 int ex,ey,ez; 14 int dx[]={1,-1,0,0,0,0}; 15 int dy[]={0,0,1,-1,0,0}; 16 int dz[]={0,0,0,0,1,-1}; 17 int bfs(){ 18 queue<Node> que; 19 Node t; 20 t.x=sx; 21 t.y=sy; 22 t.z=sz; 23 que.push(t); 24 while(que.size()){ 25 Node p=que.front(); 26 que.pop(); 27 if(p.x==ex&&p.y==ey&&p.z==ez) return dis[ex][ey][ez]; 28 for(int i=0;i<6;i++){ 29 int nx,ny,nz; 30 nx=p.x+dx[i]; 31 ny=p.y+dy[i]; 32 nz=p.z+dz[i]; 33 if(nx>=0&&nx<L&&ny>=0&&ny<R&&nz>=0&&nz<C&&dis[nx][ny][nz]==0&&space[nx][ny][nz]!='#'){ 34 dis[nx][ny][nz]=dis[p.x][p.y][p.z]+1; 35 t.x=nx;t.y=ny;t.z=nz; 36 que.push(t); 37 } 38 } 39 } 40 return dis[ex][ey][ez]; 41 } 42 43 44 int main(){ 45 while(cin>>L>>R>>C){ 46 memset(dis,0,sizeof(dis)); 47 memset(space,0,sizeof(space)); 48 if(L==0&&R==0&&C==0) break; 49 for(int i=0;i<L;i++) 50 for(int j=0;j<R;j++) 51 for(int k=0;k<C;k++) 52 { 53 cin>>space[i][j][k]; 54 } 55 56 for(int i=0;i<L;i++) 57 for(int j=0;j<R;j++) 58 for(int k=0;k<C;k++) 59 { 60 if(space[i][j][k]=='S') { 61 sx=i; 62 sy=j; 63 sz=k; 64 } 65 if(space[i][j][k]=='E') { 66 ex=i; 67 ey=j; 68 ez=k; 69 } 70 } 71 int ans= bfs(); 72 if(ans==0) printf("Trapped!\n"); 73 else printf("Escaped in %d minute(s).\n",ans); 74 } 75 return 0; 76 }
T4POJ-3278
问题分析:这是一个一维的寻找最短路径的问题,不过起点坐标的变换有向左一步,向右一步,坐标*2三种方式。于是利用三个if语句,进行bfs即可。全局数组初始值为0,所以不用memset();
1 #include<iostream> 2 #include<cstring> 3 #include<queue> 4 using namespace std; 5 const int maxn=100005; 6 int N,K; 7 int visit[maxn]; 8 int step[maxn]; 9 bool let(int u) 10 { 11 if(u<0||u>100000||visit[u]) 12 return 0; 13 return 1; 14 } 15 queue<int> que; 16 int bfs(){ 17 que.push(N); 18 while(que.size()){ 19 int u; 20 u=que.front(); 21 que.pop(); 22 if(u==K) { 23 cout<<visit[u]; 24 return 0; 25 } 26 if(let(u+1)) { 27 visit[u+1]=visit[u]+1; 28 que.push(u+1); 29 } 30 if(let(u-1)) { 31 visit[u-1]=visit[u]+1; 32 que.push(u-1); 33 } 34 if(let(2*u)) { 35 visit[2*u]=visit[u]+1; 36 que.push(2*u); 37 } 38 } 39 } 40 int main(){ 41 cin>>N>>K; 42 bfs(); 43 return 0; 44 }
T5 HDU-1312
问题分析:一道简单的DFS搜索题目,因为有多组输入,记得在每次输入之后把标记数组visit清空。
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 const int maxw=25; 5 const int maxh=25; 6 int dx[4]={1,-1,0,0}; 7 int dy[4]={0,0,1,-1}; 8 char map[maxw][maxh]; 9 int visit[maxw][maxh]; 10 int W,H,ans; 11 void dfs(int x,int y){ 12 for(int i=0;i<4;i++){ 13 int nx=x+dx[i]; 14 int ny=y+dy[i]; 15 if(nx>=0&&nx<W&&ny>=0&&ny<H&&map[nx][ny]=='.'&&!visit[nx][ny]) 16 { 17 ans++; 18 visit[nx][ny]=1; 19 dfs(nx,ny); 20 } 21 } 22 23 } 24 int main(){ 25 while(cin>>H>>W){ 26 memset(visit,0,sizeof(visit)); 27 int sx,sy; 28 ans=1; 29 if(W==0&&H==0) break; 30 for(int i=0;i<W;i++) 31 for(int j=0;j<H;j++) 32 cin>>map[i][j]; 33 for(int i=0;i<W;i++) 34 for(int j=0;j<H;j++) 35 if(map[i][j]=='@'){ 36 sx=i; 37 sy=j; 38 break; 39 } 40 dfs(sx,sy); 41 cout<<ans<<endl; 42 } 43 return 0; 44 }