最小总代价(vijos 1456)
好激动~这道题自己做的~没有看题解~~~
昨天打完网络赛,有道状压dp的题,lx分分钟把他秒了,而我却感觉很难,就是这道南京的网络赛E题
这题跟网络赛那道还有点不一样,还要记录上一次是从谁那里转移过来的,我就多开了一维, <nobr aria-hidden="true"> dp[sta][i] </nobr> <math xmlns="http://www.w3.org/1998/Math/MathML"> <mi> d </mi> <mi> p </mi> <mo stretchy="false"> [ </mo> <mi> s </mi> <mi> t </mi> <mi> a </mi> <mo stretchy="false"> ] </mo> <mo stretchy="false"> [ </mo> <mi> i </mi> <mo stretchy="false"> ] </mo> </math> 表示当前转态是 <nobr aria-hidden="true"> sta </nobr> <math xmlns="http://www.w3.org/1998/Math/MathML"> <mi> s </mi> <mi> t </mi> <mi> a </mi> </math> 并且这一次是填的第 <nobr aria-hidden="true"> i </nobr> <math xmlns="http://www.w3.org/1998/Math/MathML"> <mi> i </mi> </math> 位,然后状压转移就行了
#include"bits/stdc++.h"
#define out(x) cout<<#x<<"="<<x
#define C(n,m) (m>n?0:(long long)fac[(n)]*invf[(m)]%MOD*invf[(n)-(m)]%MOD)
using namespace std;
typedef long long LL;
const int maxn=1<<21;
const int MOD=1e9+7;
int a[20][20];
int dp[maxn][20];//dp[sta][i]表示现在是状态是sta,并且最后是放在第i位的
int main()
{
int N;
while(cin>>N)
{
for(int i=1;i<=N;i++)for(int j=1;j<=N;j++)cin>>a[i][j];
for(int sta=0;sta<(1<<N);sta++)
{
for(int i=1;i<=N;i++)dp[sta][i]=1e9;
}
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)dp[(1<<(i-1))][j]=0;//初始化,一开始就在第i个人手里
}
for(int sta=0;sta<(1<<N);sta++)
{
for(int k=1;k<=N;k++)//枚举物品
{
if((sta&(1<<(k-1)))==(1<<(k-1)))continue;//说明当前状态本来就有这个物品
int now=sta|(1<<(k-1));
for(int i=1;i<=N;i++)//枚举是第几个人传过来的
{
if((sta&(1<<(i-1)))!=(1<<(i-1)))continue;//从有的物品里转移过去
dp[now][k]=min(dp[now][k],dp[sta][i]+a[i][k]);
}
}
}
int Min=1e9;
for(int i=1;i<=N;i++)Min=min(Min,dp[(1<<N)-1][i]);
cout<<Min<<endl;
}
}