You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
|
|
#include <bits/stdc++.h>
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
typedef long long LL;
|
|
|
|
|
|
|
|
|
|
const int N = 20;
|
|
|
|
|
int a[N], c[N][N];
|
|
|
|
|
int K;
|
|
|
|
|
int n, m;
|
|
|
|
|
LL f[1 << N][N], ans;
|
|
|
|
|
|
|
|
|
|
//统计某个状态中数字1的数量
|
|
|
|
|
int count(int x) {
|
|
|
|
|
int res = 0;
|
|
|
|
|
for (int i = 0; i < 32; i++) res += x >> i & 1;
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
|
cin >> n >> m >> K;
|
|
|
|
|
for (int i = 0; i < n; i++) { //下标从0开始
|
|
|
|
|
cin >> a[i];
|
|
|
|
|
f[1 << i][i] = a[i]; //只吃一个的初始化
|
|
|
|
|
}
|
|
|
|
|
while (K--) {
|
|
|
|
|
int x, y, w;
|
|
|
|
|
cin >> x >> y >> w;
|
|
|
|
|
x--, y--; //状态压缩的套路
|
|
|
|
|
c[x][y] = w; //记录x,y的前后关联关系
|
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < (1 << n); i++) { //枚举所有状态
|
|
|
|
|
for (int j = 0; j < n; j++) { //枚举每一位
|
|
|
|
|
if ((i & (1 << j)) == 0) continue; //不包含j的不是本次要计算的状态
|
|
|
|
|
for (int k = 0; k < n; k++) { //枚举前一次最后一个菜k,看看会不会获取到更大的满意度
|
|
|
|
|
/*
|
|
|
|
|
1、本轮吃下j,最后形成i这样的状态,那么上轮没有j,状态为 i^(1<<j)
|
|
|
|
|
2、上轮的状态是固定的,那么上轮的什么是不固定的呢?
|
|
|
|
|
答案:最后吃的是什么不固定!我们需要枚举所有上轮最后一个菜吃的是什么东西。
|
|
|
|
|
很显然,上轮最后一个菜不能是j。
|
|
|
|
|
如果上轮最后一个菜是k,本轮还只能吃j,则本轮的结果中必然包含k!
|
|
|
|
|
如果不包含k,那么k是天上掉下来的吗?这就是本题的状态之间关联关系的推导过程
|
|
|
|
|
由此可见,状态压缩DP的精髓在于:
|
|
|
|
|
状态的转移关系确定!
|
|
|
|
|
*/
|
|
|
|
|
if (j == k || (!(i & (1 << k))))continue;//相同或没吃过k不合法
|
|
|
|
|
//dp转移方程
|
|
|
|
|
f[i][j] = max(f[i][j], f[i ^ (1 << j)][k] + a[j] + c[k][j]);
|
|
|
|
|
}
|
|
|
|
|
//已经吃了m个菜就统计答案
|
|
|
|
|
if (m == count(i))ans = max(ans, f[i][j]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
printf("%lld\n", ans);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|