首页 > 代码库 > HDU Victor and World (最短路+状态压缩)
HDU Victor and World (最短路+状态压缩)
题目链接:传送门
题意:
n个城市m条路。刚開始在点1,求把每一个城市都遍历一边最后回到1的花费的最小值。
分析:
我们首先须要预处理出随意两个国家之间的最短距离。由于数据范围非常小,所以直接用Floyd即可了。之后,我们用f[S][i]表示訪问国家的情况为S,当前最后訪问的一个国家是i所须要的最小总油量。当中。S的二进制表示记录了訪问国家的情况,S在二进制表示下的第i位(无论是从左往右还是从右往左都能够)假设是1则表示第i个国家被訪问过了,否则表示第i个国家没有被訪问过,那么f[S|(1<<i)][i]=min(f[S][j]+f[i][j])。当中i和j满足S&(1<<j)=1且S&(1<<i)=0。最開始时,除了f[1][1]是0,其它情况都是无穷大,之后先枚举S,再枚举i(我验题的时候由于这里搞反结果WA了)。那么终于的答案就是min(f[(1<<n)-1][i]+f[i][1])。当中i∈ [2,n]。
总复杂度为O(n?3??+n?2???2?n??)。
转自Bestcode。
以下说说我的状态转移,首先也处理好了每两个城市之间的最短路。
然后DP[S][J]S转换成二进制后1代表去过,0代表没有去过最后留在J的最小花费,然后就枚举S没有去过的城市k
DP[S|(1<<k)][k]=min(DP[S][j]+mp[j][k])
代码例如以下:
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; const int maxn = 18; const int inf = 0x3f3f3f3f; int dp[1<<maxn][maxn]; int mp[maxn][maxn]; void init(){ memset(dp,inf,sizeof(dp)); for(int i=0;i<maxn;i++) for(int j=0;j<maxn;j++) mp[i][j]=inf; } int main() { int t,n,m; scanf("%d",&t); while(t--){ init(); scanf("%d%d",&n,&m); for(int i=0;i<m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); mp[u][v]=min(mp[u][v],w); mp[v][u]=min(mp[v][u],w); } for(int i=0;i<maxn;i++) mp[i][i]=0; for(int k=1;k<=n;k++){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]); } } } dp[1][1]=0; for(int i=0;i<(1<<n);i++){ for(int j=0;j<n;j++){ if(!(i&(1<<j))){ for(int k=1;k<=n;k++){ dp[i|(1<<j)][j+1]=min(dp[i|(1<<j)][j+1],dp[i][k]+mp[k][j+1]); } } } } int ans = inf; for(int i=1;i<=n;i++) ans = min(ans,dp[(1<<n)-1][i]+mp[i][1]); printf("%d\n",ans); } return 0; }
HDU Victor and World (最短路+状态压缩)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。