剪枝1:在同一个维度上的点具有相同的奇偶性,如果奇数数量只有奇数个那么一定不能返回原点。
剪枝2:当前位置怎么也走不回去。
3:沿途判断障碍即可。
在oj上提交0.347s,最快的0.012s,应该有更好的做法。
#include<bits/stdc++.h> const char *bin = "ensw"; const int dx[] = {1,0, 0,-1}; const int dy[] = {0,1,-1, 0}; const int maxn = 230;//1+...20 const int o = 115; const int N = 24; const int nxt_dir[5][4] = {{1,2},{0,3},{0,3},{1,2},{0,1,2,3}}; const int deg[5] = {2,2,2,2,4}; int vis[maxn][maxn]; int n; int sum[N]; int left[N]; int path[N]; int cnt; void dfs(int x,int y,int d,int dir) { if(d++ == n ){ if(x == o && y == o){ for(int i = 0; i < n; i++){ printf("%c",bin[path[i]]); } putchar(' '); cnt++; } return ; } for(int i = 0; i < deg[dir]; i++){ int j = nxt_dir[dir][i]; int nx = x+dx[j]*d, ny = y+dy[j]*d; if(vis[nx][ny]) continue; if(abs(nx-o) + abs(ny-o) > left[d]) continue; bool flag = false; if(j == 0|| j == 3){ for(int tx = x+dx[j]; tx != nx ; tx+=dx[j]){ if(!~vis[tx][y]) {flag = true; break;} } }else { for(int ty = y+dy[j]; ty != ny ; ty+=dy[j]){ if(!~vis[x][ty]) {flag = true; break;} } } if(flag) continue; path[d-1] = j; vis[nx][ny] = 1; dfs(nx,ny,d,j); vis[nx][ny] = 0; } } int main() { // freopen("in.txt","r",stdin); int T; scanf("%d",&T); for(int i = 1; i < N; i++) sum[i] = sum[i-1]+i; while(T--){ int k; scanf("%d%d",&n,&k); if(((n>>1)&1)^(n&1)) { printf("Found 0 golygon(s). "); continue; } int tx,ty; memset(vis,0,sizeof(vis)); for(int i = 0; i < k; i++){ scanf("%d%d",&tx,&ty); if(abs(tx)<o && abs(ty)<o ) vis[tx+o][ty+o] = -1; } for(int i = 1; i < n; i++) left[i] = sum[n] - sum[i]; cnt = 0; dfs(o,o,0,4); printf("Found %d golygon(s). ",cnt); } return 0; }