码迷,mamicode.com
首页 > 其他好文 > 详细

状态压缩dp

时间:2021-04-10 13:21:09      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:展示   有一个   pre   false   main   include   std   压缩   表示   

最短Hamilton路径

给定一张 nn 个点的带权无向图,点从 0n?10~n?1 标号,求起点 00 到终点 n?1n?1 的最短 Hamilton 路径。

Hamilton 路径的定义是从 0,0 到 n?1,n?1 不重不漏地经过每个点恰好一次。

输入格式

第一行输入整数 nn。

接下来 n,n 行每行 n,n 个整数,其中第 ii 行第 jj 个整数表示点 ii 到 jj 的距离(记为 a[i,j]a[i,j])。

对于任意的 x,y,zx,y,z,数据保证 a[x,x]=0a[x,y]=a[y,x]a[x,x]=0,a[x,y]=a[y,x] 并且 a[x,y]+a[y,z]a[x,z]a[x,y]+a[y,z]≥a[x,z]。

输出格式

输出一个整数,表示最短 Hamilton 路径的长度。

数据范围

1n20
0a[i,j]1e7

输入样例:

5
0 2 4 5 1
2 0 6 5 3
4 6 0 8 3
5 5 8 0 5
1 3 3 5 0

输出样例:

18

分析:
  他的题意是不重不漏的经过每一个点求出他的最短路径,假如只有4个点0,1,2,3 , 那么0 -> 1 -> 2 -> 3 和 0 -> 2 -> 1 -> 3 是属于从1号点到3号点的两个不同走法,但是他俩只有一个最小
值,他俩路径有一个共同点就是起点和终点一样,所以咱们可以把状态压缩成f[state][j],这个数组的含义是状态state终点是j的集合的路径最小值,状态转移的话,可以进行如下状态转移 ->
f[state][j] = min(f[state - (1<<j)][k] + weight[k][j],f[state][j]),这是代码的实现,下面讲一下思路,就是找一个没有j的状态state_k,然后加上k到j的距离,下面展示一下代码:
 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 const int N = 25,M = (1<<20)+10;
 5 int f[M][N],weight[N][N];
 6 int main(){
 7     int n;
 8     cin>>n;
 9     for(int i=0;i<n;i++)
10         for(int j=0;j<n;j++)
11             cin>>weight[i][j];
12     memset(f,0x3f,sizeof f);
13     f[1][0] = 0;
14     for(int i=0;i < 1<<20 ;i++)
15         for(int j=0;j<n;j++)
16             if(i>>j & 1){
17                 for(int k=0;k<n;k++)
18                 if(i - (1<<j) >> k & 1)//这个地方判断k有没有确实特别的精妙
19                 f[i][j] = min(f[i][j],f[i-(1<<j)][k] + weight[k][j]);
20             }
21     cout<<f[(1<<n)-1][n-1]<<endl;
22     return 0;
23 }

 




状态压缩dp

标签:展示   有一个   pre   false   main   include   std   压缩   表示   

原文地址:https://www.cnblogs.com/QDUshy/p/14639149.html

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