vijos 1456 最小总代价

最小总代价(vijos 1456)

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

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

这题跟网络赛那道还有点不一样,还要记录上一次是从谁那里转移过来的,我就多开了一维, dp[sta][i] d p [ s t a ] [ i ] 表示当前转态是 sta s t a 并且这一次是填的第 i i <script type="math/tex" id="MathJax-Element-95">i</script> 位,然后状压转移就行了

#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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值