Codeforces 580D-Kefa and Dishes(状压DP)

原题链接:http://codeforces.com/problemset/problem/580/D

题意:在n个数字中有顺序地选择m个数字,每个数字对应有个值ai,每取一个数字答案加上ai,并且存在k个关系:x y c,如果x恰好排在y的前面,那么答案再加上ci的值。输出最大值。

思路:状压dp。dp[i][j]中,i是已经选了若干个数的情况,j是最后一个被选取的数,i从选取1个到m个枚举下去,j从第1个数到第n个数进行枚举就能得到答案。

AC代码:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 typedef long long LL;
 6 LL a[20],d[20][20],pos[20];
 7 LL dp[1<<19][20];
 8 int main()
 9 {
10     pos[0]=1;
11     for(int i=1;i<=19;i++) pos[i]=pos[i-1]<<1;
12     memset(dp,0, sizeof(dp));
13     memset(d, 0, sizeof(d));
14     int n,m,k,x,y,c;
15     scanf("%d %d %d", &n, &m, &k);
16     for(int i=0;i<n;i++) scanf("%I64d", a+i);
17     for(int i=0;i<k;i++){
18         scanf("%d %d %d",&x, &y, &c);
19         x--,y--;
20         d[x][y]=c;
21     }
22     int num;
23     for(int i=0;i<n;i++) dp[pos[i]][i]=a[i];
24
25     for(int t=1;t<m;t++){
26         for(int i=0;i<n;i++){
27             for(int j=0;j<pos[n];j++){
28                 if(j&pos[i]) continue;
29
30                 num=0;//cout<<‘*‘<<endl;
31                 k=j;
32                 while(k){
33                     if(k&1)
34                         num++;
35                     k>>=1;
36                 }
37                 if(num!=t) continue;
38
39                 for(int s=0;s<n;s++)
40                     if(s!=i&&(j&pos[s])){
41                         dp[j|pos[i]][i]=max(dp[j|pos[i]][i], dp[j][s]+d[s][i]+a[i]);
42                         //cout<<s<<‘ ‘<<j<<‘ ‘<<i<<‘ ‘<<d[s][i]<<‘ ‘<<dp[j|pos[i]][i]<<endl;
43                     }
44
45             }
46         }
47     }
48
49     LL ans=0;
50     for(int i=0;i<pos[n];i++){
51         num=0;
52         k=i;
53         while(k){
54             if(k&1)
55                 num++;
56             k>>=1;
57         }
58         if(num!=m) continue;
59
60         for(int j=0;j<n;j++) if(pos[j]&i) ans=max(ans, dp[i][j]);
61     }
62     printf("%I64d\n", ans);
63     return 0;
64 }
时间: 2024-08-05 15:14:40

Codeforces 580D-Kefa and Dishes(状压DP)的相关文章

Codeforces 580D Kefa and Dishes(状态压缩DP)

题目链接:http://codeforces.com/problemset/problem/580/D 题目大意:有n盘菜每个菜都有一个满意度,k个规则,每个规则由x y c组成,表示如果再y之前吃x那么满意度会额外增加c,现在凯迪想吃m盘菜,并且满意度最大,请求出满意度.解题思路:状压DP,设dp[i][j]表示在状态i并且最后一道菜放在位置j时的最大满意度.注意要处理好一道菜时的情况,以及注意二进制表示中1的个数超过m的情况. 代码: 1 #include<bits/stdc++.h> 2

CF580D Kefa and Dishes 状压dp

When Kefa came to the restaurant and sat at a table, the waiter immediately brought him the menu. There were n dishes. Kefa knows that he needs exactly m dishes. But at that, he doesn't want to order the same dish twice to taste as many dishes as pos

Codeforces Round #321 (Div. 2) D. Kefa and Dishes (状压dp,再A一发)

题意: 有n个菜,需要m个菜,k个规则  每个菜吃下去的满足感为 a1......an 每个规则: 吃完第u个菜后吃第v个菜满足感+c; 问:怎么吃才能幸福感最大? dp[1<<18][20]:一维表示吃了的菜(1表示吃了,0表吃没吃),第二维表示最后一个吃的菜 dp的初始化: dp[1<<i][i] = saty[i]; 状态转移:dp[i|(1 << k)][k] = max(dp[i][j] + rule[j][k] + safy[k],dp[i|(1 <&

dp + 状态压缩 - Codeforces 580D Kefa and Dishes

Kefa and Dishes Problem's Link Mean: 菜单上有n道菜,需要点m道.每道菜的美味值为ai. 有k个规则,每个规则:在吃完第xi道菜后接着吃yi可以多获得vi的美味值. 问:最多可以获得多少美味值? (1≤m≤n≤18,0≤k≤n∗(n−1)) analyse: 经典的状压DP. 由于最多18道菜,可用一个数s(s<=2^18)来唯一标识一种状态. 对于一个状态s,枚举两个位置i和j:i从已选择的菜中选定,j从未选择的菜中选定. 下一个状态ss的就是:吃完i后接着

Codeforces Gym 100676G Training Camp 状压dp

http://codeforces.com/gym/100676 题目大意是告诉你要修n门课,每门课有一个权值w[i], 在第k天修该课程讲获得k*w[i]的学习点数,给出了课程与先修课程的关系,要修该课程必须修完先修课程.问最多能学到多少点数. 非常简单的一道状压dp(一开始我还误导队友写成两维的去了 T^T); dp[s] : s 的二进制存放的是已经选择的课程,在该状态下的能获得的最大的点数. 这时如果再学一门课程k,将转移到状态ss (s | (1 << k) ) ,能否转移需要判断合

Codeforces 11D - A Simple Task (状压DP)

题意 求出一个n个点m个边的图,求简单环有多少(没有重复点和边). 思路 这是个不错的题,这个状压dp保存的状态不是直接的环,而是路径的个数.s表示的状态为一条路径,则dp[s][i]表示以s的最小编号为起点,以i为终点的环的个数.那么我们就可以通过枚举状态,枚举状态中的起点和枚举路径外的终点,然后判断终点和起点是否相连来判断是否成环. 代码 #include <stdio.h> #include <string.h> #include <iostream> #incl

Codeforces 482C. Game with Strings 状压DP

很好的状压dp题目 d[mask]=x   在询问了mask位的情况下,有x状态的串还是不能区分 /// 预处理不好会TLE dp[x]  从一次也没有问,到问到状态x时的概率 可以看 http://blog.csdn.net/houserabbit/article/details/40658791 大神的题解 C. Game with Strings time limit per test 1 second memory limit per test 256 megabytes input s

Codeforces 895C Square Subsets(状压DP 或 异或线性基)

题目链接  Square Subsets 这是白书原题啊 先考虑状压DP的做法 2到70总共19个质数,所以考虑状态压缩. 因为数据范围是70,那么我们统计出2到70的每个数的个数然后从2考虑到70. 设dp[x][mask]为考虑到x这个数的时候,x这个数和之前的所有数中,选出某些数,他们的乘积分解质因数,所有的指数对2取模之后, 状态为mask的方案数. 然后就可以转移了……这个状压DP花了我好几个小时……真是弱啊 哦对最后还要特判1的情况. 每个1选或不选都可以,然后考虑只选1的情况,累加

Codeforces 580D Kefa and Dishes(状压DP)

题目大概说要吃掉n个食物里m个,吃掉各个食物都会得到一定的满意度,有些食物如果在某些食物之后吃还会增加满意度,问怎么吃满意度最高. dp[S][i]表示已经吃掉的食物集合是S且刚吃的是第i个食物的最大满意度 ..没什么好说的 1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 5 int val[18],pairs[18][18]; 6 long long d[1<<18][18]; 7 8