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 possible.
Kefa knows that the i-th dish gives him a
Of course, our parrot wants to get some maximal possible satisfaction from going to the restaurant. Help him in this hard task!
InputThe first line of the input contains three space-separated numbers, n, m and k (1 ≤ m ≤ n ≤ 18, 0 ≤ k ≤ n * (n - 1)) — the number of dishes on the menu, the number of portions Kefa needs to eat to get full and the number of eating rules.
The second line contains n space-separated numbers ai, (0 ≤ ai ≤ 109) — the satisfaction he gets from the i-th dish.
Next k lines contain the rules. The i-th rule is described by the three numbers xi, yi and ci (1 ≤ xi, yi ≤ n, 0 ≤ ci ≤ 109). That means that if you eat dish xi right before dish yi, then the Kefa's satisfaction increases by ci. It is guaranteed that there are no such pairs of indexes i and j (1 ≤ i < j ≤ k), that xi = xj and yi = yj.
OutputIn the single line of the output print the maximum satisfaction that Kefa can get from going to the restaurant.
Examples Input Copy2 2 1Output Copy
1 1
2 1 1
3Input Copy
4 3 2Output Copy
1 2 3 4
2 1 5
3 4 2
12Note
In the first sample it is best to first eat the second dish, then the first one. Then we get one unit of satisfaction for each dish and plus one more for the rule.
In the second test the fitting sequences of choice are 4 2 1 or 2 1 4. In both cases we get satisfaction 7 for dishes and also, if we fulfill rule 1, we get an additional satisfaction 5.
題意翻譯
kefa進入了一家餐廳,這家餐廳中有n個菜(0<n<=18),kefa對第i個菜的滿意度為ai(0<=ai<=10^9),並且對於這n個菜有k個規則,如果kefa在吃完第xi個菜之後吃了第yi個菜(保證xi、yi不相等),那麼會額外獲得ci(0<=ci<=10^9)的滿意度。kefa要吃m道任意的菜(0<m<=n),但是他希望自己吃菜的順序得到的滿意度最大,請你幫幫kefa吧!
輸入第一行是三個數:n,m,k
第二行是n個數,第i個數表示kefa對第i道菜的滿意度為ai
第三行到第k+2行每行有3個數:xi,yi,ci,表示如果kefa在吃完第xi道菜之後立刻吃了第yi道菜,則會額外獲得ci的滿意度
Ps:這道題是個狀壓,因為n,m的範圍都很小
n,m很小,那麼狀壓再轉移即可;
#include<iostream> #include<cstdio> #include<algorithm> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<map> #include<set> #include<vector> #include<queue> #include<bitset> #include<ctime> #include<deque> #include<stack> #include<functional> #include<sstream> //#include<cctype> //#pragma GCC optimize("O3") using namespace std; #define maxn 300005 #define inf 0x3f3f3f3f #define INF 9999999999 #define rdint(x) scanf("%d",&x) #define rdllt(x) scanf("%lld",&x) #define rdult(x) scanf("%lu",&x) #define rdlf(x) scanf("%lf",&x) #define rdstr(x) scanf("%s",x) typedef long long ll; typedef unsigned long long ull; typedef unsigned int U; #define ms(x) memset((x),0,sizeof(x)) const long long int mod = 1e9 + 7; #define Mod 1000000000 #define sq(x) (x)*(x) #define eps 1e-3 typedef pair<int, int> pii; #define pi acos(-1.0) //const int N = 1005; #define REP(i,n) for(int i=0;i<(n);i++) typedef pair<int, int> pii; inline ll rd() { ll x = 0; char c = getchar(); bool f = false; while (!isdigit(c)) { if (c == '-') f = true; c = getchar(); } while (isdigit(c)) { x = (x << 1) + (x << 3) + (c ^ 48); c = getchar(); } return f ? -x : x; } ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a%b); } ll sqr(ll x) { return x * x; } /*ll ans; ll exgcd(ll a, ll b, ll &x, ll &y) { if (!b) { x = 1; y = 0; return a; } ans = exgcd(b, a%b, x, y); ll t = x; x = y; y = t - a / b * y; return ans; } */ ll qpow(ll a, ll b, ll c) { ll ans = 1; a = a % c; while (b) { if (b % 2)ans = ans * a%c; b /= 2; a = a * a%c; } return ans; } int n, m, k; ll dp[(1<<18)+6][20]; ll a[maxn]; ll ret[20][20]; int main() { //ios::sync_with_stdio(0); rdint(n); rdint(m); rdint(k); int cnt = 0; for (int i = 0; i < n; i++)rdllt(a[i]); for (int i = 0; i < k; i++) { ll x, y, z; rdllt(x); rdllt(y); rdllt(z); ret[x - 1][y - 1] = z; } for (int i = 0; i < n; i++) { dp[1 << (i)][i] = a[i]; } ll maxx = -1; for (int i = 0; i < (1 << n); i++) {// 列舉狀態 cnt = 0; for (int j = 0; j < n; j++) { if (i&(1 << j)) {// 看該位是否為1 cnt++; for (int k = 0; k < n; k++) {// 選擇吃下一個 if (!(i&(1 << k))) { dp[i | (1 << k)][k] = max(dp[i|(1 << k)][k], dp[i][j] + a[k] + ret[j][k]); // dp 轉移 } } } } if (cnt == m) {// 滿足 m for (int j = 0; j < n; j++) if (i&(1 << j))maxx = max(maxx, dp[i][j]); } } cout << (ll)maxx << endl; return 0; }