题目描述
某乡有nn个村庄(1<n le 201<n≤20),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)s(0<s<1000)是已知的,且AA村到BB村与BB村到AA村的路大多不同。为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为11,他不知道选择什么样的路线才能使所走的路程最短。请你帮他选择一条最短的路。
输入格式
村庄数nn和各村之间的路程(均是整数)。
输出格式
最短的路程。
输入输出样例
输入 #1
3 0 2 1 1 0 2 2 1 0
输出 #1
3
说明/提示
输入解释
33 {村庄数}
0 2 1021 {村庄11到各村的路程}
1 0 2102 {村庄22到各村的路程}
2 1 0210 {村庄33到各村的路程}
题解:我一开始还以为是最短路,后来仔细一看原来是DP
如果考场的话我会先写全排列拿部分分,再慢慢写状压DP
#include<cstdio> #include<iostream> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<bits/stdc++.h> typedef long long ll; using namespace std; const int oo=0x3f3f3f3f; int ans=oo,n,a[22][22],f[1100011][21]; int main(){ freopen("1171.in","r",stdin); freopen("1171.out","w",stdout); scanf("%d",&n); for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&a[i][j]); memset(f,0x3f,sizeof(f)); f[1][0]=0; int mx=1<<n; for(int s=0;s<mx;s++){ for(int i=0;i<n;i++){ if(f[s][i]==oo) continue;//i位为1才可推过来 for(int j=0;j<n;j++){ if(((s>>j)&1)==0){//j位为0 int now=s|(1<<j); f[now][j]=min(f[now][j],f[s][i]+a[i][j]); } } } } for(int i=0;i<n;i++) ans=min(ans,f[(1<<n)-1][i]+a[i][0]); cout<<ans; return 0; }