解题思路:直接DFS暴力枚举,注意这里的方向判断,因为不能和上次走相同或相反的方向,要做适当的处理。开始依然可以枚举四个方向,当前一个方向与现方向相同(表现为对应数值相等)或相反(表现为对应数值相加等于5),则continue跳过,具体看代码。还可作剪纸处理,当已走步数距离原点太远以至于不可能返回时剪掉(还未做剪纸处理)。
题目大意:输入两个整数n(表示走几次)k(表示障碍物个数),每走一次步数大小等于次数的数值大小,并且必须左转或者右转(不能直走或往回走),问第n次走完正好返回原点(0,0)的行走方案有多少个,结果按字典序输出。
Sample Input
2 8 2 -2 0 6 -2 8 2 2 1 -2 0
Sample Output
wsenenws Found 1 golygon(s). Found 0 golygon(s).
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=200;
bool mark[200+maxn][200+maxn];
int n,k,count1,ans[101];
char alpha[6]=" ENSW";
int go[5][2]={
0,0,
0,1,
-1,0,
1,0,
0,-1};
void DFS(int x,int y,int cur,int fa) //分别对于位置坐标,第几次行走以及方向
{
ans[cur]=fa;
if(cur==n)
{
if(x==0&&y==0) //满足第n次返回原点
{
for(int i=1;i<=cur;i++) cout<<alpha[ans[i]]; cout<<endl;
count1++;return;
}
return;
}
for(int i=1;i<=4;i++)
{
if(fa==i||fa+i==5) continue; //注意!!巧妙地处理相同方向或相反方向,值得借鉴!
int nx=x,ny=y; bool judge=false;
for(int k=1;k<=cur+1;k++)
{
nx+=go[i][0];
ny+=go[i][1];
if(mark[nx+maxn][ny+maxn]==true) judge=true; //行走过程中碰瓷
}
if(judge==false) //不会碰瓷则深搜枚举
DFS(nx,ny,cur+1,i);
}
}
int main()
{
int T; cin>>T;
while(T--)
{
cin>>n>>k;
count1=0;
memset(mark,false,sizeof(mark));
for(int i=0;i<k;i++)
{
int x,y; cin>>x>>y;
mark[-y+maxn][x+maxn]=true; //这里的障碍物坐标需要注意
}
DFS(0,0,0,2);
DFS(0,0,0,1);
cout<<count1<<endl;
}
return 0;
}