题意
给出一副 m x n 的图,要求把整幅图在每个点只走一次,每次可以走“日”字,每次可以任意一个八个方向之一的前提下,每个点都走到;并且按照 日 字走。
最后每个点都可以走一遍的话,按照字典序从小到大输出路径;否则输出 impossible 。
最后注意有几个换行。
思路
题目让我们输出路径,一看就知道是DFS。之后flag标记是否找到路径,找到的话直接 . first转换成%c 和 .second 输出就行。
我感觉我都不如我大一时候,因为我纠结好久如何去走出日字,其实就是判断方向的数组to的八个方向变一下,变成可以与坐标轴形成日的坐标。也就是:
int to[8][2]= {{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}}; // 走“日”字
顺便借用本题复习一下 vector + pari + make_pair 的用法。
其他就是我有一个问题:dfs进去的时候有一个flag,那个flag为啥需要判断 !flag 才能进去呢,不判断就wa???
AC代码
#include<iostream>
#include<cmath>
#include<string.h>
#include<vector>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<stdio.h>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
int a[30][30],n,m;
//int to[8][2]={0,1,0,-1,-1,0,1,0,-1,1,1,1,-1,-1,1,-1};
int to[8][2]= {{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}}; // 走“日”字
bool book[30][30],flag;
vector<pair<int,int> >v; // vector<int>v;
void dfs(int x,int y,int step)
{
if(step>=n*m)//if(step>=x*y) // 如何判断一幅图已经全部遍历到了?
{
//flag=1;
if(!flag)
{
flag=1;
for(int i=0; i<v.size(); i++)
printf("%c%d",v[i].first+'A'-1,v[i].second);
}
return ;
}
for(int i=0; i<8; i++)
{
int tx=x+to[i][0];
int ty=y+to[i][1];
if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&!book[tx][ty])
{
book[tx][ty]=1;
v.push_back(make_pair(tx,ty));
dfs(tx,ty,step+1);
v.pop_back(); // dont forget
book[tx][ty]=0;
}
}
}
int main()
{
int T,cas=1;
cin>>T;
while(T--)
{
cin>>m>>n; //走 "日" 字
memset(book,0,sizeof(book));
v.clear();
flag=0,book[1][1]=1;
v.push_back(make_pair(1,1));
cout<<"Scenario #"<<cas++<<":"<<endl;
dfs(1,1,1); // x y step
if(!flag)
cout<<"impossible";
cout<<endl<<endl;
}
return 0;
}