codevs2596 售貨員的難題(狀壓dp)
阿新 • • 發佈:2017-06-25
樹狀dp min fault 極限 iostream mut 通過 cnblogs 表示
題目描述 Description
2596 售貨員的難題
時間限制: 1 s 空間限制: 32000 KB 題目等級 : 鉆石 Diamond
題目描述 Description
某鄉有n個村莊(1<n<=15),有一個售貨員,他要到各個村莊去售貨,各村莊之間的路程s(0<s<1000)是已知的,且A村到B村與B村到A村的路大多不同。為了提高效率,他從商店出發到每個村莊一次,然後返回商店所在的村,假設商店所在的村莊為1,他不知道選擇什麽樣的路線才能使所走的路程最短。請你幫他選擇一條最短的路。
輸入描述 Input Description村莊數n和各村之間的路程(均是整數)
輸出描述 Output Description最短的路程
樣例輸入 Sample Input3
0 2 1
1 0 2
2 1 0
樣例輸出 Sample Output3
數據範圍及提示 Data Size & Hint本題可用最短路思想、搜索來解決,但是可能無法通過一組極限數據(且效率較低)。建議按樹狀DP考慮
/*
狀壓dp入門題
f[i][j]表示當前狀態為i,走到第j個城市最短路徑
相應的狀態轉移方程為f[i][j]=min( f[i^(1<<j)][k]+g[k][j]);
i^(1<<j)的意思是將j這個城市從i狀態中去掉.g[k][j]是k和j之間的距離。
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 50010
using namespace std;
int n,g[20][20],f[maxn][20],ans;
int min(int x,int y){return x<y?x:y;}
int main()
{
scanf("%d",&n);n--;
memset(f,127/3,sizeof(f));
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
scanf("%d",&g[i][j]);
ans=f[0][0];f[0][0]=0;
for(int i=1;i<(1<<n);i++)
for(int j=1;j<=n;j++)if(i&(1<<j-1))
for(int k=0;k<=n;k++)
f[i][j]=min(f[i][j],f[i^(1<<j-1)][k]+g[k][j]);
for(int i=1;i<=n;i++)
ans=min(ans,f[(1<<n)-1][i]+g[i][0]);
printf("%d\n",ans);
return 0;
}
codevs2596 售貨員的難題(狀壓dp)