hihocoder Hamiltonian Cycle(记忆化搜索+剪枝)
来源:互联网 发布:淘宝网排行榜在哪里 编辑:程序博客网 时间:2024/06/14 01:47
题目链接:点击打开链接
题意描述:
给定一个有向图,求图中哈密顿回路的数量。
哈密顿回路,具体到本题中即从某一个点开始经过所有的点一次后再回到该点的不同路径数。对于这个不同需要注意两点:
如果我们将路径经过的点按顺序写下,比如当n=3时,若存在123和231。此时,我们认为这两条路径是同一条哈密顿回路。而123和213则是不同的哈密顿回路。
若两个点之间有多条边,经过不同的边的路径仍然看作同一条哈密顿回路。不同哈密顿回路只和经过的点有关。因此对于多条边的情况我们可以将其合并为一条边来考虑。
对于哈密顿回路,一个简单的想法就是枚举所有可能的路径,判定这个路径是否存在。即时间复杂度为O(n!)。而题目给定的数据范围为:n <= 12,所以最大可能的枚举次数为12! = 479,001,600。
极限的数据不到5亿,所以我们可以考虑使用暴力来枚举所有的哈密顿回路。直接采用DFS枚举我们的每一步,最后判定是否走回到起点。
解题思路:记忆花搜索+剪枝
分析:显然如果按照上述方法直接暴搜很容易超时,分析题意我们可以采用记忆化搜索,记录dp[i][j],i表示到达第i的节点,j表示已经走过那些点
同时由于结点数比较少,所以我们可以采用位运算,这样判断是否已经走过所有定点可以在o(1)的时间内完成
代码:
#include <cstdio>#include <cstring>#define MAXN 13using namespace std;bool g[MAXN][MAXN];///去重边bool vv[MAXN][1<<12];///vv[i][j]这种状态是否已经访问过,记忆化搜索使用int dp[MAXN][1<<12];///dp[i][j]状态表示到达点i时所有经过图中点的状态j的方案数int head[MAXN],tol;struct node{ int to,next;}edge[210];void addEdge(int x,int y){ edge[tol].to=y;edge[tol].next=head[x];head[x]=tol++;}int vis,flag;int n,m,ans;void dfs(int rt){ if(vv[rt][vis]) { ans+=dp[rt][vis];return;}///如果已经访问过,直接加上dp即可 else { vv[rt][vis]=true; for(int k=head[rt];k!=-1;k=edge[k].next){ int i=edge[k].to; if(g[rt][i]){ if(i==1&&vis==(1<<n)-1){///判断形成哈密顿回路,位运算使O(n)变为o(1) dp[rt][vis]++; ans++; continue; } if(!(vis&(1<<(i-1)))&&((vis&flag)!=flag)){///剪枝,如果剩下的点都不能到达1则剪掉 vis=vis|(1<<(i-1)); dfs(i); dp[rt][vis^(1<<(i-1))]+=dp[i][vis];///更新状态 vis=vis^(1<<(i-1)); } } } }}int main(){ while(scanf("%d%d",&n,&m)!=EOF){ memset(g,false,sizeof(g)); memset(head,-1,sizeof(head)); tol=0; int x,y; flag=0; for(int i=1;i<=m;++i) { scanf("%d%d",&x,&y); if(!g[x][y]){///去除重边 g[x][y]=true; addEdge(x,y); if(y==1) flag|=(1<<(x-1));///记录哪些点可以回到点1,用于剪枝 } } memset(vv,false,sizeof(vv)); memset(dp,0,sizeof(dp)); ans=0; vis=1; dfs(1); printf("%d\n",ans); } return 0;}
0 0
- hihocoder Hamiltonian Cycle(记忆化搜索+剪枝)
- hihoCoder 1087 Hamiltonian Cycle
- hihocoder 1087 : Hamiltonian Cycle
- hiho1087 Hamiltonian Cycle 位运算+记忆化搜索 求哈密顿回路数量
- hdu1072Nightmare(dfs+剪枝,记忆化搜索)
- hihocoder 1103 数位dp+记忆化搜索
- Hamiltonian Cycle
- hdu 1240 深度优先搜索+剪枝(记忆化搜索)
- 记忆化搜索--剪枝 vijos Function(Function(F...
- 递归优化 POJ1579 记忆化搜索 剪枝 去掉重复计算
- POJ 3317 博弈-极大极小过程+记忆化搜索+剪枝
- ZOJ 3644 Kitty's Game(记忆化搜索+剪枝)
- [hihocoder 1033]交错和 数位dp/记忆化搜索
- 记忆化搜索之一: hihoCoder 1491 : Monster Killing
- hihocoder 1323 回文字符串 区间dp OR 记忆化搜索
- 《Hamiltonian Cycle》题目分析
- hiho Hamiltonian Cycle
- 1122. Hamiltonian Cycle (25)
- SVN分支和标记用法
- 程序员的自我修养——链接,装载与库(第1,2部分)
- linear regression example
- 抓包工具:Fiddler 2-强大效能之二 AutoResponder
- 剑指offer在线编程题汇总与讲解(part 1)
- hihocoder Hamiltonian Cycle(记忆化搜索+剪枝)
- Oracle中varchar ,varchar2的区别
- Matlab处理数据完成后自动发送邮箱提醒
- 顺序表(C++语言实现)
- web.xm里过滤器过滤之后,String类型的数据还是乱码解决方案
- windows批处理命令大全
- 黑马程序员--指针与变量
- log4j 详解和使用
- 程序员的自我修养——链接,装载与库(第3,4部分)