vijos 1456 最小总代价

最小总代价(vijos 1456)

题目链接:https://vijos.org/p/1456

好激动~这道题自己做的~没有看题解~~~
昨天打完网络赛,有道状压dp的题,lx分分钟把他秒了,而我却感觉很难,就是这道南京的网络赛E题

这题跟网络赛那道还有点不一样,还要记录上一次是从谁那里转移过来的,我就多开了一维, d p [ s t a ] [ i ] 表示当前转态是 s t a 并且这一次是填的第 i 位,然后状压转移就行了

#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;
    }
}

猜你喜欢

转载自blog.csdn.net/SwustLpf/article/details/82312956