ch0103 位运算,简单状压dp
Posted edmunds
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ch0103 位运算,简单状压dp相关的知识,希望对你有一定的参考价值。
题意:n个顶点带权无向图,求最短hamilton路径长度(从起点0走到终点n-1,且经过每个顶点恰好一次的路径)
在看位运算的时候做到这题,觉得状态压缩的思路挺奇特的。本来n<20,O(n!*n)的算法肯定炸了,但是可以二进制表示状态
如果将i表示为二进制,i的第j位走过就为1,没走过就为0(注意二进制位从0~n-1),此处1<=i<2^n-1
用dp[i][j]表示状态i,到达第j个城市的最小值,那么i的二进制第j位为1(到达第j个城市),且i的二进制第j位取反之后,二进制第k位为1(没到达第j个城市前,到达过第k个城市)
满足这两个条件之后,转移方程为:dp[i][j]=min(dp[i][j],dp[i^(1<<j)][k]+w[k][j]),
先把dp数组初始化为inf,再初始化dp[1][0]=0(开始在第0个城市),答案为dp[(1<<n)-1][n-1]。
贴个代码
#include<bits/stdc++.h> using namespace std; const int inf=0x3f3f3f3f; const int maxn=10; int main() { int n,i,j,k,t; int w[maxn][maxn]; int dp[1<<maxn][maxn]; cin>>n; for (i=0;i<n;i++) for (j=0;j<n;j++) cin>>w[i][j]; memset(dp,inf,sizeof(dp)); dp[1][0]=0; for (i=1;i<(1<<n);i++) for (j=0;j<n;j++) if ((i>>j)&1) //i的二进制第j位=1(当前二进制状态下,经过第j个城市) for (k=0;k<n;k++) if ((i^(1<<j))>>k&1) //第j位取反后,第k个城市走过 dp[i][j]=min(dp[i][j],dp[i^(1<<j)][k]+w[k][j]); cout<<dp[(1<<n)-1][n-1]<<endl; //+-的优先级比>>大... return 0; }
以上是关于ch0103 位运算,简单状压dp的主要内容,如果未能解决你的问题,请参考以下文章