https://www.luogu.org/problemnew/show/P1171
题目背景
数据有更改
题目描述
某乡有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到各村的路程}
n<=20裸的状压
最好写我为人人,枚举状态最好放在最外层
最后强制返回
#include<cstdio>
#include<iostream>
using namespace std;
const int N=30;
int n,w[N][N],f[25][1050000],ans=2e9;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) scanf("%d",&w[i][j]);
for(int i=1;i<=n;i++)
for(int S=0;S<1<<n-1;S++) f[i][S<<1|1<<0]=2e9;
f[1][1]=0;
for(int S=0;S<1<<n-1;S++)
{
for(int i=1;i<=n;i++)
if(1<<i-1&(S<<1|1<<0))
for(int j=1;j<=n;j++)
if(!(1<<j-1&(S<<1|1<<0)))
f[j][S<<1|1<<j-1|1<<0]=min(f[j][S<<1|1<<j-1|1<<0],f[i][S<<1|1<<0]+w[i][j]);
}
for(int i=1;i<=n;i++)
ans=min(ans,f[i][(1<<n)-1]+w[i][1]);
printf("%d\n",ans);
return 0;
}