codeforces#580 D. Kefa and Dishes(状压dp)

题意:有n个菜,每个菜有个兴奋值,并且如果吃饭第i个菜立即吃第j个菜,那么兴奋值加ma[i][j],求吃m个菜的最大兴奋值,(n<=18)

 

分析:定义dp[status][last],status为每道菜的状态,1为吃,0为不吃,last为最后一个菜,dp[status][last],在status状态下最后吃last的最大兴奋值,然后枚举status去更新后面的状态,详细见代码

 

AC代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,k;
ll w[20],ma[20][20],dp[(1<<18)+10][20],ans=0;
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m>>k;
    for(int i=0;i<n;i++)
        cin>>w[i];
    for(int i=1;i<=k;i++)
    {
        int a,b;
        ll c;
        cin>>a>>b>>c;
        ma[a-1][b-1]=c;
    }
    for(int i=0;i<n;i++)
        dp[(1<<i)][i]=w[i];
    for(int i=0;i<(1<<n);i++)
    {
        int cnt=0;
        for(int j=0;j<n;j++)//当前状态可以转移到“当前状态+一个菜”
        {
            if((i&(1<<j))==0)continue;
            cnt++;
           // cout<<cnt<<endl;
            for(int k=0;k<n;k++)//找到一个当前状态不吃的菜,用当前状态去更新吃第k个菜的状态
            {
                if((i&(1<<k))==1)continue;
                dp[(i^(1<<k))][k]=max(dp[(i^(1<<k))][k],dp[i][j]+w[k]+ma[j][k]);
            }
        }
        if(cnt==m)
            for(int j=0;j<n;j++)ans=max(ans,dp[i][j]);
    }
    cout<<ans<<endl;
    return 0;
}

  

posted @ 2018-11-15 16:54  czh~  阅读(146)  评论(0编辑  收藏  举报