luoguP1171 售货员的难题
luoguP1171 售货员的难题
题目描述
某乡有 n个村庄( 1<n≤20 ),有一个售货员,他要到各个村庄去售货,各村庄之间的路程 s(0<s<1000)是已知的,且 A 村到 B 村与 B 村到 A 村的路大多不同。
为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为 1 ,
他不知道选择什么样的路线才能使所走的路程最短。请你帮他选择一条最短的路。
输入输出格式
输入格式:
村庄数 n 和各村之间的路程(均是整数)。
输出格式:
最短的路程。
输入输出样例
说明
输入解释
3 {村庄数}
0 2 1 {村庄 1 到各村的路程}
1 0 2 {村庄 2 到各村的路程}
2 1 0 {村庄 3 到各村的路程}
Solution
状压DP
DP[S][j]表示当走过的村庄状态为S且现在在第J个村庄的路程
答案为min{dp[ALL][i]+dis[i][1]}
#include<bits/stdc++.h> using namespace std; #define MAXN 21 #define all (1<<n)-1 int n; int dis[MAXN][MAXN]; int dp[1<<20][MAXN]; int ans=1<<30; int main() { scanf("%d",&n); memset(dp,127,sizeof(dp)); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&dis[i][j]); dp[1][1]=0; for(int i=0;i<=all;i++) for(int j=1;j<=n;j++) if(!((1<<(j-1))&i)) for(int k=1;k<=n;k++) if((1<<(k-1))&i) dp[i|(1<<j-1)][j]=min(dp[i][k]+dis[k][j],dp[i|(1<<j-1)][j]); for(int i=1;i<=n;i++) ans=min(ans,dp[all][i]+dis[i][1]); printf("%d\n",ans); }