标签:onclick mes cli src 跳过 code ++ 思考 col
一个正方形的镇区分为N×N个小方块(1≤N≤7)。农场位于方格的左上角,集市位于左下角。奶牛Bessie穿过小镇。从左上角走到左下角,每次可以走上,下,左,右,但不能走出方格的外面,每个格经过且仅经过一次。当N=3时,贝茜的漫游路径可能如下图所示:
写一个程序,对于给出的N值,计算Bessie从农场走到集市有多少条路径。
一行,一个整数N。(1≤N≤7)
只有一行。输出一个整数表示路径的数量。
2
1
明显求哈密顿路径,不知道图论里有没有能快速切这题的算法。(话说还在网上看到了基于cdq论文的题解,学不来,弃了)
搞不了图论就dfs加剪枝吧。综合众多题解总结了2个剪枝优化。
剪枝1:
找当前点的必经点。
容易想到,如果相邻点的出度为1,那么这个点就是必经点。如果有多个必经点,那就可以想到无论怎么走都走不出哈密顿路径,回溯即可;如果没有必经点,把相邻点都搜一遍即可。
注意,终点判断必经点是判断出度是否为0(自己思考为什么)。
剪枝2:
找当前点的必不经点。
这个有点难想。我们可以思考,如果走了一个点,把整张图分成若干个部分,那么显然遍历不了整张图。
这里为了防止剪枝负优化,只采用了判断是否会分成两个部分的剪枝。
如果当前点的相邻点出度为2,且出点在同行或同列,那就可以想到走这个点必定将图分成两个部分,直接跳过即可。
综上,一个时间复杂度十分低的程序就出来了。但事实上,本人还是认为这题有更多的剪枝方案。先放着,留到以后再想。
#include <iostream> using namespace std; const int dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1}; int n, lim; int out[10][10]; bool f[10][10]; int ans; void DFS(int x, int y, int dep) { if(x == n && y == 1) { if(dep == lim) ++ans; return; } f[x][y] = 1; int cnt = 0, p; for(register int i = 0; i < 4; ++i) { --out[x + dx[i]][y + dy[i]]; } int tx, ty; for(register int i = 0; i < 4; ++i) { tx = x + dx[i]; ty = y + dy[i]; if(f[tx][ty]) continue; if(tx != n || ty != 1) { if(out[tx][ty] == 1) ++cnt, p = i; } else { if(!out[tx][ty]) ++cnt, p = i; } } if(cnt == 1) DFS(x + dx[p], y + dy[p], dep + 1); else if(!cnt) { for(register int i = 0; i < 4; ++i) { tx = x + dx[i]; ty = y + dy[i]; if(f[tx][ty]) continue; if(out[tx][ty] == 2) { if(f[tx - 1][ty] && f[tx + 1][ty] && (f[tx][ty - 1] ^ 1) && (f[tx][ty + 1] ^ 1)) continue; if((f[tx - 1][ty] ^ 1) && (f[tx + 1][ty] ^ 1) && f[tx][ty - 1] && f[tx][ty + 1]) continue; } DFS(tx, ty, dep + 1); } } for(register int i = 0; i < 4; ++i) { ++out[x + dx[i]][y + dy[i]]; } f[x][y] = 0; return; } int main() { cin >> n; lim = n * n; for(register int i = 0; i <= n + 1; ++i) { f[0][i] = f[n + 1][i] = f[i][0] = f[i][n + 1] = 1; } for(register int i = 1; i <= n; ++i) { for(register int j = 1; j <= n; ++j) { out[i][j] = 4; if(i == 1 || i == n) --out[i][j]; if(j == 1 || j == n) --out[i][j]; } } DFS(1, 1, 1); cout << ans; return 0; }
标签:onclick mes cli src 跳过 code ++ 思考 col
原文地址:https://www.cnblogs.com/kcn999/p/10778168.html