码迷,mamicode.com
首页 > 编程语言 > 详细

【算法学习笔记】62.状态压缩 DP SJTU OJ 1088 邮递员小F

时间:2015-07-07 00:43:00      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:

状态压缩,当我们的状态太多时可以考虑用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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!