POJ2488/openjudge 1490 A Knight's Journey  解题报告(dfs)

来源:互联网 发布:人工智能对政治的影响 编辑:程序博客网 时间:2024/05/08 01:02

A Knight’s Journey
总时间限制: 1000ms 内存限制: 65536kB
描述
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 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, …
给你两个数p,q代表行与列(或列与行,可自己决定)。p*q代表格子数,这里的q(列的坐标)用A,B,C…..代替1,2,3……,p(行的坐标)还是用1,2,3,4….表示
输出
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.
输出就是把路径输出,并且每组数据之间有一个空行

样例输入
3
1 1
2 3
4 3
样例输出
Scenario #1:
A1

Scenario #2:
impossible

Scenario #3:
A1B3C1A2B4C2A3B1C3A4B2C4

底部还有91组测试数据。

题目分析:

简单的dfs寻找最优路径问题,但这里的最优路径有两个条件。①必须可以走完所有格子且不重复 ②需率先走字典序小的那个路径。

这里问题①很好解决。主要问题是②如何解决。
里面的白点就代表着骑士可以走的格子
我们将图上的点抽象一下。
这里有一个很巧妙的方法:

这里将@看做是骑士,0看做是能走的位置。

1 2 3 4 # # # # # # # A # # 0 # 0 # # B # 0 # # # 0 # # # # @ # # # C # 0 # # # 0 # D # # 0 # 0 # # # # # # # # #

因为我们的行列分别是用数字和字母编号的,那么我们也可以将骑士所能走的八个方向按字典序从小到大排序进行排序
从图可知 A2 < A3 < B1 < B4 < C1 < C4 < D2 < D3
从而我们可以这样定义:
c代表列,r代表行
(dc[0],dr[0])就代表图中的A2点
const int dc[]={-1,1,-2,2,-2,2,-1,1};
const int dr[]={-2,-2,-1,-1,1,1,2,2};

  • 注意1 <= p*q <= 26 说明p,q的最大值可以达到26。

具体代码

采用了 vector数组 ,判定成立的条件就是当数组大小等于p*q时,说明以全部走完。

#include <iostream>#include <cstring>#include <algorithm>#include <string>#include <vector>#include <string>using namespace std;vector<string> v;//存储路径//八个方向,按字典序排序const int dc[]={-1,1,-2,2,-2,2,-1,1};const int dr[]={-2,-2,-1,-1,1,1,2,2};int R,C;//边界int vis[27][27];//标记数组bool ok = true;void dfs(int r,int c);string int_s(int r,int c)//将(x,y)坐标转变为字母加数字{    string a;    char ch1,ch2;    ch1 = r-1  + 'A';    ch2 = c+'0';    a=a+ch1;    a=a+ch2;    return a;//返回一个string}int main(){    int n;    cin>>n;    for(int i = 1; i <= n; i++)    {        //初始化        ok = true;        memset(vis, 0, sizeof(vis));        cin>>C>>R;        v.clear();//记得清空        v.push_back(int_s(1, 1));        vis[1][1]=1;        dfs(1,1);//从起点1,1开始        //初始化        cout<<"Scenario #"<<i<<":"<<endl;;        if(v.size()!=R*C)//如果最后的路径等于所有的格子说明有解,否则无解            ok=false;        if(ok)        {            for(vector<string>::iterator it=v.begin();it!=v.end();it++)//输出vector的所有内容                cout<<*it;            cout<<endl;        }        else            cout<<"impossible"<<endl;        cout<<endl;    }    return 0;}void dfs(int r,int c){    for(int i=0;i<8;i++)//八个方向    {        int tmp_r=r,tmp_c=c;        r+=dr[i];c+=dc[i];        if(!vis[r][c]&&r>=1&&r<=R&&c>=1&&c<=C)        {            vis[r][c]=1;//标记            v.push_back(int_s(r, c));//该点压入数组            dfs(r,c);            if(v.size()==R*C)//如果已经到了这一步说明全部的格子都已走完,就可以直接结束递归,将所有栈帧释放                break;//这里的break可以省掉一大笔时间            v.pop_back();//走到这说明刚刚上一条路径不同,则需把刚刚压入数组的点释放出来            vis[r][c]=0;//还原变量            r=tmp_r;c=tmp_c;        }        r=tmp_r;c=tmp_c;//记得还原    }}
911 11 21 31 41 51 61 71 81 91 101 111 121 131 141 151 161 171 181 191 201 211 221 231 241 251 262 12 22 32 42 52 62 72 82 92 102 112 122 133 13 23 33 43 53 63 73 84 14 24 34 44 54 65 15 25 35 45 56 16 26 36 47 17 27 38 18 28 39 19 210 110 211 111 212 112 213 113 214 115 116 117 118 119 120 121 122 123 124 125 126 1
Scenario #1:A1Scenario #2:impossibleScenario #3:impossibleScenario #4:impossibleScenario #5:impossibleScenario #6:impossibleScenario #7:impossibleScenario #8:impossibleScenario #9:impossibleScenario #10:impossibleScenario #11:impossibleScenario #12:impossibleScenario #13:impossibleScenario #14:impossibleScenario #15:impossibleScenario #16:impossibleScenario #17:impossibleScenario #18:impossibleScenario #19:impossibleScenario #20:impossibleScenario #21:impossibleScenario #22:impossibleScenario #23:impossibleScenario #24:impossibleScenario #25:impossibleScenario #26:impossibleScenario #27:impossibleScenario #28:impossibleScenario #29:impossibleScenario #30:impossibleScenario #31:impossibleScenario #32:impossibleScenario #33:impossibleScenario #34:impossibleScenario #35:impossibleScenario #36:impossibleScenario #37:impossibleScenario #38:impossibleScenario #39:impossibleScenario #40:impossibleScenario #41:impossibleScenario #42:impossibleScenario #43:A1C2A3B1D2B3C1A2C3D1B2D3Scenario #44:impossibleScenario #45:impossibleScenario #46:A1B3D2F1G3E2G1F3E1G2E3C2A3B1C3A2C1D3B2D1F2Scenario #47:A1B3C1A2C3D1B2D3E1G2E3C2A3B1D2F1H2F3G1E2G3H1F2H3Scenario #48:impossibleScenario #49:impossibleScenario #50:A1B3C1A2B4C2A3B1C3A4B2C4Scenario #51:impossibleScenario #52:A1B3C1A2B4D3E1C2D4E2C3A4B2D1E3C4A3B1D2E4Scenario #53:A1B3C1A2B4C2D4E2F4D3E1F3D2B1A3C4B2A4C3E4F2D1E3F1Scenario #54:impossibleScenario #55:impossibleScenario #56:impossibleScenario #57:A1B3A5C4D2B1A3B5D4C2B4A2C1D3C5A4B2D1C3D5Scenario #58:A1B3A5C4A3B1D2E4C5A4B2D1C3B5D4E2C1A2B4D5E3C2E1D3E5Scenario #59:impossibleScenario #60:impossibleScenario #61:impossibleScenario #62:A1B3A5C6D4B5D6C4D2B1A3C2B4A2C1D3B2D1C3D5B6A4C5A6Scenario #63:impossibleScenario #64:impossibleScenario #65:A1B3C1A2C3B1A3C2B4A6C7B5A7C6A5B7C5A4B2C4B6Scenario #66:impossibleScenario #67:impossibleScenario #68:A1B3C1A2B4C2A3B1C3A4B2C4A5B7C5A6B8C6A7B5C7A8B6C8Scenario #69:impossibleScenario #70:impossibleScenario #71:impossibleScenario #72:impossibleScenario #73:impossibleScenario #74:impossibleScenario #75:impossibleScenario #76:impossibleScenario #77:impossibleScenario #78:impossibleScenario #79:impossibleScenario #80:impossibleScenario #81:impossibleScenario #82:impossibleScenario #83:impossibleScenario #84:impossibleScenario #85:impossibleScenario #86:impossibleScenario #87:impossibleScenario #88:impossibleScenario #89:impossibleScenario #90:impossibleScenario #91:impossible