[CF580D]Kefa and Dishes(状压dp)

题目链接:http://codeforces.com/contest/580/problem/D

题意:n道菜选m道,每道菜有满意度,两道菜之间有满意度加成,注意满意度加成是满足顺序的,比如x和y的满意度是z,那么x一定要在y的左边。问m道菜选出来最大的满意度是多少。

状压dp,要多考虑一个问题就是,选出来菜还要排放顺序。

设dp(i,j)为状态i的时候最后一道菜是j的最大满意度。首先枚举状态,接着枚举最后一道菜j,枚举到j后即可枚举j道菜之前那道菜k(不能重复)。如果存在则状态由dp(pre,k)转移而来,pre为不包含j时的状态。dp(i,j)=max(dp(i,j),dp(pre,k)+d(j)+c(k,j)),d(j)表示j的满意度,c(k,j)表示k和j两道菜放在一起时的满意度。

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <iomanip>
 4 #include <cstring>
 5 #include <climits>
 6 #include <complex>
 7 #include <fstream>
 8 #include <cassert>
 9 #include <cstdio>
10 #include <bitset>
11 #include <vector>
12 #include <deque>
13 #include <queue>
14 #include <stack>
15 #include <ctime>
16 #include <set>
17 #include <map>
18 #include <cmath>
19 using namespace std;
20 #define fr first
21 #define sc second
22 #define cl clear
23 #define BUG puts("here!!!")
24 #define W(a) while(a--)
25 #define pb(a) push_back(a)
26 #define Rint(a) scanf("%d", &a)
27 #define Rll(a) scanf("%I64d", &a)
28 #define Rs(a) scanf("%s", a)
29 #define Cin(a) cin >> a
30 #define FRead() freopen("in", "r", stdin)
31 #define FWrite() freopen("out", "w", stdout)
32 #define Rep(i, len) for(int i = 0; i < (len); i++)
33 #define For(i, a, len) for(int i = (a); i < (len); i++)
34 #define Cls(a) memset((a), 0, sizeof(a))
35 #define Clr(a, x) memset((a), (x), sizeof(a))
36 #define Full(a) memset((a), 0x7f7f7f, sizeof(a))
37 #define lrt rt << 1
38 #define rrt rt << 1 | 1
39 #define pi 3.14159265359
40 #define RT return
41 #define lowbit(x) x & (-x)
42 #define onecnt(x) __builtin_popcount(x)
43 typedef long long LL;
44 typedef long double LD;
45 typedef unsigned long long ULL;
46 typedef pair<int, int> pii;
47 typedef pair<string, int> psi;
48 typedef pair<int, int> pll;
49 typedef map<string, int> msi;
50 typedef vector<int> vi;
51 typedef vector<int> vl;
52 typedef vector<vl> vvl;
53 typedef vector<bool> vb;
54 
55 const int maxn = 19;
56 const int maxm = (1 << maxn);
57 LL dp[maxm][maxn];
58 int c[maxn][maxn];
59 int d[maxn];
60 int n, m, k;
61 
62 signed main() {
63     // FRead();
64     int x, y, z;
65     while(~scanf("%d%d%d",&n,&m,&k)) {
66         Cls(c); Cls(d);
67         Rep(i, n) Rint(d[i]);
68         Rep(i, k) {
69             scanf("%d%d%d",&x,&y,&z);
70             x--, y--;
71             c[x][y] = z;
72         }
73         LL ret = 0;
74         int nn = 1 << n;
75         Rep(i, nn) {
76             Rep(j, n) {
77                 int pre = i ^ (1 << j);
78                 dp[i][j] = d[j];
79                 if(i & (1 << j)) {
80                     Rep(k, n) {
81                         if(j != k && ((1 << k) & i)) {
82                             dp[i][j] = max(dp[i][j], dp[pre][k]+d[j]+c[k][j]);
83                         }
84                     }
85                 }
86                 if(__builtin_popcount(i) == m) ret = max(ret, dp[i][j]);
87             }
88         }
89         cout << ret << endl;
90     }
91     RT 0;
92 }
原文地址:https://www.cnblogs.com/kirai/p/5837247.html