题目背景
数据有更改
题目描述
某乡有n个村庄(1<n<20),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且A村到B村与B村到A村的路大多不同。为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为1,他不知道选择什么样的路线才能使所走的路程最短。请你帮他选择一条最短的路。
输入输出格式
输入格式:
村庄数n和各村之间的路程(均是整数)。
输出格式:
最短的路程。
输入输出样例
输入样例#1:
3
0 2 1
1 0 2
2 1 0
输出样例#1:
3
说明
输入解释
3 {村庄数}
0 2 1 {村庄1到各村的路程}
1 0 2 {村庄2到各村的路程}
2 1 0 {村庄3到各村的路程}
题目链接:https://www.luogu.org/problem/show?pid=1171#sub
解题报告
傻逼状压DP,没了!!!
AC代码
#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#define INF (1<<28)
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
using namespace std;
int f[1<<20][20];
int one[20];
int zero[20];
int r[21][21];
int n,ans,m,o,z;
inline int min(int x,int y){
return x<y?x:y;
}
int main(){
scanf("%d",&n);
FOR(i,0,n-1)
FOR(j,0,n-1)
scanf("%d",&r[i][j]);
m=(1<<n)-1;
FOR(i,0,m)
FOR(j,0,n-1)
f[i][j]=INF;
f[1][0]=0;
for(register int i=1;i<=m;i+=2){
one[0]=zero[0]=0;
FOR(j,0,n-1)
i&(1<<j)?one[++one[0]]=j:zero[++zero[0]]=j;
FOR(k,1,one[0])
FOR(j,1,zero[0]){
o=one[k];
z=zero[j];
f[i|(1<<z)][z]=min(f[i|(1<<z)][z],f[i][o]+r[o][z]);
}
}
ans=INF;
FOR(i,1,n-1)
ans=min(ans,f[m][i]+r[i][0]);
cout<<ans<<endl;
return 0;
}