zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    08-12 NOIP模拟测试18
    08-09 NOIP模拟测试15
    08-11 NOIP模拟测试17
    08-10 NOIP模拟测试16
    08-07 NOIP模拟测试14
    08-03 NOIP模拟测试12
    [SDOI2011]拦截导弹
    08-01 NOIP模拟测试11
    零散知识点
    07-29 NOIP模拟测试10
  • 原文地址:https://www.cnblogs.com/edmunds/p/12300540.html
Copyright © 2011-2022 走看看