脑残强迫症数学家进大观园,每次走上一次走的步数+1的时候就要左/右转。规定了谜之数字n之后,最后一次行进的步数必须等于n。还愣头青不会绕障碍(大概是处女座,觉得绕过之后走成的路径不完美),问题:如何正确的回家
因为谜之数字n最多20,根据小学算术1+2+...+20应该等于210,也就是说傻逼数学家一天之内走的路不会超过210,那么想要成功折返的话最多往一个方向走105步(实际应该小于105因为不可能一直走)。所以我开一个250*250的数组作为地图,起始点设为(110,110)。
因为要打印路径,又要字典序最小,自然又是dfs。貌似可以加入"不可能按时返回"剪枝,不过并不是必须。
Run Time: 1.548s
#define UVa "7-2.225.cpp"
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
//Global Variables.
int laststep, blkn;
int dir[2][4] = {{1, 0, 0, -1},{0, 1, -1, 0}}; //lexicographics: e, n, s, w
int dir_availability[5][4] = {{0,1,1,0},{1,0,0,1},{1,0,0,1},{0,1,1,0}, {1,1,1,1}};
char dirname[4] = {'e', 'n', 's', 'w'};
int step[25];
int vis[250][250];
int cnt;
int startx = 110, starty = 110;
/////
int dfs(int d, int x, int y, int direction) {
if(d == laststep + 1) {
if(x == startx && y == starty) {
for(int i = 1; i < d; i ++)
printf("%c", dirname[step[i]]);
printf("\n");
cnt ++;
}
else return 0;
}
else {
if((laststep*laststep - d*d) / 2 < (x - 110 + y - 110)) return 0;
for(int i = 0; i < 4; i ++) {
int nx = x + dir[0][i] *d , ny = y + dir[1][i] * d; //walking
if(nx > 0 && nx < 250 && ny > 0 && ny < 250 && !vis[nx][ny] && dir_availability[direction][i]) { //if you walked to the boundaries, there would be no hope to be back on time.
int ok = 1;
if(i == 0 || i == 3) for(int m = min(x,nx); m <= max(x,nx); m ++) {
if(vis[m][y] == -1) { //way blocked.
ok = 0;
break;
}
}
else if(i == 1 || i == 2) for(int m = min(y,ny); m < max(y,ny); m ++) {
if(vis[x][m] == -1) { //way blocked.
ok = 0;
break;
}
}
if(ok) {
vis[nx][ny] = 1;
step[d] = i;
dfs(d + 1, nx, ny, i);
vis[nx][ny] = 0;
}
}
}
}
}
int main() {
int kase;
scanf("%d", &kase);
while(kase --) {
cnt = 0;
memset(vis, 0, sizeof(vis));
vis[0][0] = 1;
scanf("%d%d", &laststep, &blkn);
while(blkn --) {
int a, b;
scanf("%d%d", &a, &b);
vis[startx+a][starty+b] = -1;
}
dfs(1, startx, starty, 4);
printf("Found %d golygon(s).\n\n", cnt);
}
return 0;
}