CF D. Kefa and Dishes (状态转移dp)

来源:互联网 发布:开发一个软件 编辑:程序博客网 时间:2024/05/24 07:21

题意:

一个人去点餐从n种点出m种。每一种菜都会有一个满意度,并且他制订了k个规则
,若a在b之前吃的话,会额外得到满意度。求出最大满意度。

思路:

由于问题的规模不大(1 ≤ m ≤ n ≤ 18, 0 ≤ k ≤ n * (n - 1)),所以很明显要用到状态转移
dp,若何用呢?想到需要一个状态st表示菜的选择状态,i表示以第i种菜为结尾的最大
值,则遍历st的每一种情况去求出dp[st][i].

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int MAXN = 1<<18;typedef long long LL;int n,m,k;LL dp[MAXN+10][21];int bom[30][30];int a[30];int Cnt(int st){    int res = 0;    for(int i = 0;i < n; i++) {        if(st&(1<<i))            res++;    }    return res;}int main(){    //freopen("in.txt","r",stdin);    scanf("%d%d%d",&n,&m,&k);    for(int i = 0;i < n; i++)        scanf("%d",&a[i]);    for(int i = 0;i < k; i++) {        int s,e,v;        scanf("%d%d%d",&s,&e,&v);        s--,e--;        bom[s][e] = v;    }    int maxn = 1<<n;    LL ans = 0;    for(int st = 0;st < maxn; st++) {        for(int i = 0;i < n; i++) {            if(st&(1<<i)) {                int flag = false;                for(int j = 0;j < n; j++) {                    if(j != i && st&(1<<j)) {                        flag = true;                        dp[st][i] = max(dp[st][i],dp[st^(1<<i)][j] + a[i] + bom[i][j]);                    }                }                if(!flag) {                    dp[st][i] = a[i];                }            }            if(Cnt(st) == m) {                ans = max(ans,dp[st][i]);            }        }    }    cout<<ans<<endl;    return 0;}
0 0