题意:有n盘菜,从里面选m盘可以品尝,每盘菜有一个满意值,另外有k种关系,先吃某盘菜后吃某盘的话可以增加ai满意度。
思路:约束条件有当前吃的哪盘菜,在吃这盘菜之前吃了哪几盘菜,所以定义状态是dp[i][j],表示当前让第i盘菜作为吃的最后一盘时,已经吃了菜的集合为j,获得的最大满意度;
用n位2进制表示状态,1表示吃过了这盘菜,0表示没吃,状态转移方程:dp[i][j]=max(dp[i][j],dp[k][q]+w[k][i]+a[i]),k为上一盘菜,q为上一状态;
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[20][1<<20];
ll val[20],w[20][20];
int main()
{
ll n,m,k;
while(~scanf("%lld%lld%lld",&n,&m,&k))
{
for(int i=0;i<n;i++){
scanf("%d",&val[i]);
}
ll a,b,c;
memset(w,0,sizeof(w));
for(int i=0;i<k;i++){
scanf("%lld%lld%lld",&a,&b,&c);
a--;
b--;
w[a][b]=c;
}
memset(dp,0,sizeof(dp));
ll ans=0;
for(int j=0;j<(1<<n);j++){
int sum=1;
int t=j;
while(t&(t-1)){ t=t&(t-1);sum++;}
for(int i=0;i<n;i++){
if(j&(1<<i))
for(int k=0;k<n;k++){
if(j&(1<<k)){
int q=j-(1<<i);
dp[i][j]=max(dp[i][j],dp[k][q]+val[i]+w[k][i]);
}
}
if(sum==m) ans=max(ans,dp[i][j]);
}
}
cout<<ans<<endl;
}
}