旅行商问题 —— 状态压缩DP

来源:互联网 发布:iphone照片整理软件 编辑:程序博客网 时间:2024/05/18 00:13


如果说在给定的数据类型范围内,事件的规模已经达到了  (n!)   。即使这个时候n特别小,仍然不能够都试一遍,所以需要用DP来解决。

再就是在记忆化搜索的过程中,DP的一个下标并不是整数,但是我们可以将其编码成一个整数。对于集合可以把元素的选取与否对应到一个二进制位里面,从而把状态压缩成一个整数,大大方便了计算和维护。 针对集合的DP叫做状态压缩DP。


#include <iostream>#include <cstdio>#include <cstdlib>#include <string>#include <cmath>#include <algorithm>#include <cstring>#include <map>#include <sstream>#include <queue>#include <stack>#define INF 0x3f3f3f3f#define mem(a,b) memset(a,b,sizeof(a));#define For(a,b) for(int i = a;i<b;i++)#define LL long long#define MAX_N 1005/*以下是一些位运算的操作首先一共有n个元素设定任意一个集合S一个集合T空集:                      ....... 0只含有第i个元素的集合:     ....... 1<<i含有全部n个元素的集合:    ........ (1 << n) - 1判断第i个元素是否属于集合S:  ..... if( S >> i & 1 )向集合中加入第i个元素:    ........ S | 1 << i从集合中除去第i个元素:    ........ S & ~(1 << i)集合S和集合T的并集:        ....... S | T集合S和集合T的交集:        ....... S & T*/using namespace std;int d[MAX_N][MAX_N];int dp[1<<MAX_N][MAX_N];int n;int rec(int s,int v){    if(dp[s][v] >= 0)    {        return dp[s][v];    }    if(s == (1 << n)-1 && v == 0)    {        return dp[s][v] = 0;    }    int res = INF;    for(int u = 0; u<n; u++)    {        if(!(s >> u & 1 ))        {            res = min(res,rec(s | 1 << u,u) + d[v][u]);        }    }    return dp[s][v] = res;}int main(){    scanf("%d",&n);    for(int i = 0; i<n; i++)        fill(d[i],d[i]+n,INF);    for(int i = 0; i<8; i++)    {        int v,u,cost;        scanf("%d%d%d",&v,&u,&cost);        d[v][u] = cost;    }    for(int s = 0; s < (1 << n); s++)        fill(dp[s],dp[s]+n,INF);    dp[(1 << n)-1][0] = 0;    for(int s = (1 << n)-2; s>=0; s--)    {        for(int v = 0; v<n; v++)        {            for(int u = 0; u<n; u++)            {                if(!(s >> u & 1))                {                    dp[s][v] = min(dp[s][v],dp[s | 1 << u][u] + d[v][u]);                }            }        }    }    printf("%d\n",dp[0][0]);    //rec();递归、记忆化搜索    mem(dp,-1);        printf("%d\n",rec(0,0));    return 0;}/*2017/2/8测试样例:0 1 31 2 52 3 53 4 34 0 70 3 42 0 44 1 6*/




0 0