题意:
一个人从(0,0)开始,每次走的长度是1,2,3...,每次走完一段,就必须向左或向右转,停留的点不能重复,并且不能经过障碍物;
现在给出最后一步走多远,以及障碍物的位置,求最后又走回(0,0)点的方法有几种,输出每种走法,还有走法总数;
思路:
暴力dfs();因为坐标有负数,所以我们把所有坐标+105,确保变正数;
还有一个剪枝就是,当现在的距离已经不可能回得去了,就结束;
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX = 250;
const int limit = 105;
const int N = 50;
int dir[4][2] = {{1,0},{0,1},{0,-1},{-1,0}};
char face[4] = {'e','n','s','w'};
int step[N],ans,n,m;
int sum[25];
int g[MAX][MAX];
bool judge(int x,int y, int d,int f) {
for(int i = 1; i <= d; i++) {
x += dir[f][0];
y += dir[f][1];
if(abs(x) > limit || abs(y) > limit)
return true;
if(g[x + limit][y + limit] == -1)
return true;
}
if(abs(x) + abs(y) > sum[n] - sum[d])
return true;
return false;
}
void dfs(int x, int y, int d, int f) {
if(d > n) {
if(x == 0 && y == 0) {
for(int i = 1; i <=n; i++) {
printf("%c",face[step[i]]);
}
printf("\n");
ans++;
}
return;
}
for(int i = 0; i < 4; i++) {
if(i == f || i + f == 3)
continue;
int xx = x + dir[i][0] * d;
int yy = y + dir[i][1] * d;
if(judge(x,y,d,i))
continue;
if(g[xx + limit][yy + limit])
continue;
g[xx + limit][yy + limit] = 1;
step[d] = i;
dfs(xx,yy,d + 1,i);
g[xx + limit][yy + limit] = 0;
}
}
int main() {
sum[0] = 0;
for(int i = 1; i <= 20; i++) {
sum[i] = i + sum[i - 1];
}
int t;
scanf("%d",&t);
while(t--) {
scanf("%d%d",&n,&m);
memset(g, 0, sizeof(g));
ans = 0;
int a,b;
for(int i = 0; i < m; i++) {
scanf("%d%d",&a,&b);
if(abs(a) > limit || abs(b) > limit)
continue;
g[a + limit][b + limit] = -1;
}
dfs(0,0,1,-1);
printf("Found %d golygon(s).\n\n",ans);
}
}