题意:有一个城市,一个人从城市的(0,0)出发,可以走东南西北四个方向,然后规定第一个方向走1步,左转或右转换个方向走2步,继续换方向走3步。。。,但是城市中会有一些障碍物是不能通过的,给出障碍物坐标,问走n步后是否能返回起点(0,0),如果可以输出每次走的方向,把所有可能情况全部输出。
题解:首先坐标可能出现负数,所以可以把图扩大,估算所走路径不会超过250,所以中点设为(115,115),找到转向规律,直接dfs,跑出答案发现只有走的步数是7 8 15 16时才有答案,特判其他答案是0节省时间。
#include <stdio.h>
#include <math.h>
#include <string.h>
const int N = 55;
int len, n, g[255][255], res, path[300];
int flag[4][2] = {{1, 0}, {0, 1}, {0, -1}, {-1, 0}};
char face[4] = {'e', 'n', 's' ,'w'};
bool judge(int x, int y, int cnt, int f) {
int xx = x, yy = y;
for (int i = 1; i <= cnt; i++) {
xx += flag[f][0];
yy += flag[f][1];
if (g[xx][yy] == -1)
return true;
}
return false;
}
void dfs(int x, int y, int cnt, int f) {
if (cnt > len && x == 115 && y == 115) {
for (int i = 1; i <= len; i++)
printf("%c", face[path[i]]);
printf("\n");
res++;
return;
}
if (cnt > len)
return;
for (int i = 0; i < 4; i++) {
if (f == -1 || f != i && f + i != 3) {//同方向和180度的跳过
int dx = x + flag[i][0] * cnt;
int dy = y + flag[i][1] * cnt;
if (g[dx][dy] == -1 || g[dx][dy])
continue;
if (judge(x, y, cnt, i))
continue;
g[dx][dy] = 1;
path[cnt] = i;
dfs(dx, dy, cnt + 1, i);
g[dx][dy] = 0;
}
}
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
memset(g, 0, sizeof(g));
res = 0;
scanf("%d%d", &len, &n);
int a, b;
for (int i = 0; i < n; i++) {
scanf("%d%d", &a, &b);
if (a + 115 > 250 || b + 115 > 250 || a + 115 < 0 || b + 115 < 0)
continue;
g[a + 115][b + 115] = -1;
}
if (len == 7 || len == 8 || len == 15 || len == 16) {
dfs(115, 115, 1, -1);
printf("Found %d golygon(s).\n\n", res);
}
else
printf("Found 0 golygon(s).\n\n");
}
return 0;
}