POJ2488DFS
来源:互联网 发布:美利达淘宝旗舰店 编辑:程序博客网 时间:2024/06/04 19:35
A Knight's Journey
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 45494 Accepted: 15471
Description
Background
The knight is getting bored of seeing the same black and white squares again and again and has decided to make a journey
around the world. Whenever a knight moves, it is two squares in one direction and one square perpendicular to this. The world of a knight is the chessboard he is living on. Our knight lives on a chessboard that has a smaller area than a regular 8 * 8 board, but it is still rectangular. Can you help this adventurous knight to make travel plans?
Problem
Find a path such that the knight visits every square once. The knight can start and end on any square of the board.
The knight is getting bored of seeing the same black and white squares again and again and has decided to make a journey
around the world. Whenever a knight moves, it is two squares in one direction and one square perpendicular to this. The world of a knight is the chessboard he is living on. Our knight lives on a chessboard that has a smaller area than a regular 8 * 8 board, but it is still rectangular. Can you help this adventurous knight to make travel plans?
Problem
Find a path such that the knight visits every square once. The knight can start and end on any square of the board.
Input
The input begins with a positive integer n in the first line. The following lines contain n test cases. Each test case consists of a single line with two positive integers p and q, such that 1 <= p * q <= 26. This represents a p * q chessboard, where p describes how many different square numbers 1, . . . , p exist, q describes how many different square letters exist. These are the first q letters of the Latin alphabet: A, . . .
Output
The output for every scenario begins with a line containing "Scenario #i:", where i is the number of the scenario starting at 1. Then print a single line containing the lexicographically first path that visits all squares of the chessboard with knight moves followed by an empty line. The path should be given on a single line by concatenating the names of the visited squares. Each square name consists of a capital letter followed by a number.
If no such path exist, you should output impossible on a single line.
If no such path exist, you should output impossible on a single line.
Sample Input
31 12 34 3
Sample Output
Scenario #1:A1Scenario #2:impossibleScenario #3:A1B3C1A2B4C2A3B1C3A4B2C4
Source
TUD Programming Contest 2005, Darmstadt, Germany
题意:给出制定规格的网格,问马能不能不重复的全部走完,并按字典序输出路径。
解题思路:这题显然用DFS会简单一些。开始的时候,我想的是:既然是要把所有的格子遍历一遍,而且输出的结果要以字典序的顺序输出,所以只需要调好搜索的顺序,并用数组存下路径即可。然后,经过我的多次调试,终于过了样例,以下是我的最初代码
#include <stdio.h>#include <memory.h>#include <string.h>#define maxn 30typedef struct road{ char p; char q;} T;T arr[700];int flag[maxn][maxn],m,n,a=0;void dfs(int r,int s){ if(r<0||r>=m||s<0||s>=n) return; if(flag[r][s]!=0) return; flag[r][s]=1; arr[a].p=s+'A'; arr[a].q=r+'1'; a++; dfs(r+2,s+1); dfs(r+2,s-1); dfs(r-2,s-1); dfs(r-2,s+1); dfs(r+1,s+2); dfs(r+1,s-2); dfs(r-1,s+2); dfs(r-1,s-2);}int main(){ //freopen("in.txt","r",stdin); int t; scanf("%d",&t); for(int k=1; k<=t; k++) { a=0; memset(flag,0,sizeof(flag)); scanf("%d%d",&m,&n); printf("Scenario #%d:\n",k); dfs(0,0); int f=1; for(int i=0; i<m; i++) for(int j=0; j<n; j++) if(flag[i][j]==0) f=0; if(!f) printf("impossible\n"); else { for(int i=0; i<a; i++) printf("%c%c",arr[i].p,arr[i].q); printf("\n"); } } return 0;}
结果不尽人意,果断被系统判了WA。debug调试一次后,我就明白了自己错在哪里。走到错误的路的时候,虽然搜索的进度会返回,但是flag已经标记,没有被改回来,所以后续搜索的时候会误以为此处已经在整条路径中。于是我就改用了回溯法。在走到错路的时候,返回时把flag还原回去,然后在dfs函数参数里加了路径的下标,这样保证每次存储的时候都是正确的路(就算前面存的是错误的回溯之后会重新赋值)。修改后,我的代码如下
#include <stdio.h>#include <memory.h>#include <string.h>#define maxn 30typedef struct road{ char p; char q;} T;T arr[700];int flag[maxn][maxn],m,n,a=0,success=0,vis[2][8]= {{-2,-2,-1,-1,1,1,2,2},{-1,1,-2,2,-2,2,-1,1}};void dfs(int x,int y,int a){ if(success) return; arr[a].p=x+'A'; arr[a].q=y+'1'; if(a==m*n) { success=1; return; } int yy,xx; for(int i=0; i<8; i++) { xx=x+vis[0][i]; yy=y+vis[1][i]; if(flag[xx][yy]==1) continue; if(yy<0||yy>=m||xx<0||xx>=n) continue; flag[xx][yy]=1; dfs(xx,yy,a+1); flag[xx][yy]=0; }}int main(){ //freopen("in.txt","r",stdin); int t; scanf("%d",&t); for(int k=1; k<=t; k++) { a=0; memset(flag,0,sizeof(flag)); scanf("%d%d",&m,&n); printf("Scenario #%d:\n",k); success=0; flag[0][0]=1; dfs(0,0,1); if(!success) printf("impossible\n"); else { for(int i=1; i<=m*n; i++) printf("%c%c",arr[i].p,arr[i].q); printf("\n"); } printf("\n"); } return 0;}一次AC。