题目链接: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 }