题目大意:
n个菜中选m个菜吃,每个菜有一个满意度
ai
,此外有k种情况:先吃
xi
再吃
yi
会额外增加
ci
满意度。问最大满意度。
思路:
数组dp[1
<<
<script type="math/tex" id="MathJax-Element-880"><<</script>n][n]第一维表示吃的菜,第二维表示最后吃的一个菜,
状态转移方程为:dp[i][j] = max(dp[i][j], dp[u][k] + map[k][j] + a[j]);
其中u为i去除第j个菜,k为u中最后一个菜。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 LL;
const int MAXN = 20;
LL sat[MAXN];
LL map[MAXN][MAXN];
LL dp[1<<MAXN][MAXN];
LL num[1<<MAXN];
LL sol(int n, int m)
{
memset(dp, -1, sizeof(dp));
memset(num, 0, sizeof(num));
LL ans = 0;
for(int i = 0; i < n; i++)
{
dp[1<<i][i] = sat[i];
num[1<<i] = 1;
if(m == 1)
ans = max(ans, sat[i]);
}
int t = 1 << n;
for(int i = 0; i < t; i++)
for(int j = 0; j < n; j++)
if(i&(1<<j))
{
int u = i - (1 << j);
for(int k = 0; k < n; k++)
if(dp[u][k] != -1)
{
dp[i][j] = max(dp[i][j], dp[u][k] + map[k][j] + sat[j]);
num[i] = num[u] + 1;
}
if(num[i] == m)
ans = max(dp[i][j], ans);
}
return ans;
}
int main(int argc, char const *argv[])
{
int n, m, k;
cin >> n >> m >> k;
for(int i = 0; i < n; i++)
cin >> sat[i];
memset(map, 0, sizeof(map));
while(k--)
{
int x, y;
LL c;
cin >> x >> y >> c;
map[x-1][y-1] = c;
}
cout << sol(n, m) << endl;
return 0;
}