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;
    }
    

      

  • 相关阅读:
    求有序数组中不重复数字的出现次数
    ThreadLocal在Spring事务管理中的应用
    spring声明式的事务管理
    bootstrap-table 下一页点击失效
    IE浏览器下ajax和缓存的那些事儿
    vue学习第二步——目录结构
    vue学习第一步——自动化构建项目
    bootstrap-select 默认搜索
    webuploader的一些坑
    easyUI combobox 添加空白项
  • 原文地址:https://www.cnblogs.com/edmunds/p/12300540.html
Copyright © 2011-2022 走看看