CF580D

早期DIV2场的一道D题,为了扫盲做的状压

题目很简单,把吃菜的情况状压一下,然后多记一维上一道菜吃了什么即可

 

转移方程:

dp[i][j][k]表示吃第i道菜,上一道吃的j,吃了的状态是k时的最大满足

dp[i][j][k|(1<<(t-1)]=max(dp[i][j][k|(1<<(t-1)],dp[i-1][j][k]+a[t]+G[t][j]);

注意这道题的空间会爆,所以把第一维滚动掉

下附代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #define ll long long
 5 using namespace std;
 6 ll dp[2][20][262145];
 7 ll G[20][20];
 8 ll a[20];
 9 ll n,m,k;
10 int main(){
11     memset(dp,-1,sizeof(dp));
12     memset(G,0,sizeof(G));
13     scanf("%lld%lld%lld",&n,&m,&k);
14     for (int i=1; i<=n; i++)
15         scanf("%lld",&a[i]);
16     for (int i=1; i<=k; i++){
17         ll a,b,c;
18         scanf("%lld%lld%lld",&a,&b,&c);
19         G[a][b]=c;
20     }
21     for (int i=1; i<=n; i++){
22         dp[1][i][1<<(i-1)]=a[i];
23     }
24     int flag=1;
25     for (int i=2; i<=m; i++){
26         flag=flag^1;
27         for (int j=1; j<=n; j++){
28             for (int k=1; k<=n; k++){
29                 if (k!=j){
30                     for (int t=0; t<(1<<n); t++){
31                         if (t&(1<<(k-1)) && dp[flag^1][k][t]!=-1 && (t&(1<<(j-1)))==0){
32                             dp[flag][j][t|(1<<(j-1))]=max(dp[flag][j][t|(1<<(j-1))],dp[flag^1][k][t]+a[j]+G[j][k]);
33                         }
34                     }
35                 }
36             }
37         }
38     }
39     ll res=0;
40     for (int i=1; i<=n; i++){
41         for (int j=0; j<(1<<n); j++)
42             res=max(res,dp[flag][i][j]);
43     }
44     printf("%lld",res);
45 }

 

posted @ 2020-11-24 19:52  我是菜狗QAQ  阅读(115)  评论(0编辑  收藏  举报