标签:
状态压缩,当我们的状态太多时可以考虑用bit来存储,用二进制来表示集合,用&来取交集,用^来异或。
DP过程很简单,遍历所有情况取最短路径就行,因为最短哈密顿回路本身就是一个NPC问题,效率不高。
#include <vector> #include <iostream> using namespace std; //最短哈密顿回路问题 NP完全问题。。。 int map[16][16]={0}; int n=0; const int INF=768000;//3000*16*16 int f[1<<16][16]={0};//f[i][j]表示的是 从起点开始 经过所有i中的点 到达j的最短路径长度 void initialize(){ cin>>n; for (int i = 0; i < n; ++i){ for (int j=0; j < n; ++j){ cin>>map[i][j];//输入数据 } } } int build(){ // 起点始终在列表里 那个位置一直为1 所以不用考虑起点 // DP状态压缩 比如 n=4 时 eg: 1<<3 -->表示 1000 从 0000到 1000 确定了前面3个位置的所有情况 for (int i = 0; i < ( 1 << (n-1) ); ++i)// { //要注意 输入时下标为j的点 在i中的下标为j-1 简称j点 //DP计算 f[i][j] for (int j = 1; j < n ; ++j){ if(i == ( 1 << (j-1) ))//如果此时i中正好只有j点的话 f[i][j] = map[0][j];//直接从起点到j即可 else{//否则需要dp if(i & (1 << (j-1) ))//i中有j点 { f[i][j] = INF;//开始寻找它的最小值 for( int k = 1; k < n ; ++k) if(k!=j and (i & ( 1<< (k-1) ) ) ) //找到k k不是j 且在i中 //状态转移方程如下 其实只是一个松弛操作而已 收边 f[i][j] = min(f[i^(1<<(j-1))][k] + map[k][j], f[i][j]); } } } } int res = INF; for (int i = 1; i < n; ++i) { res = min(res, f[(1<<(n-1))-1][i] + map[i][0]); } return res; } int main(int argc, char const *argv[]) { initialize(); if(n==1) cout<<2*map[0][0]<<endl; else cout<<build()<<endl; return 0; }
【算法学习笔记】62.状态压缩 DP SJTU OJ 1088 邮递员小F
标签:
原文地址:http://www.cnblogs.com/yuchenlin/p/sjtu_oj_1008.html