codeforces round 321 div2 D Kefa and Dishes(状态压缩dp)
题意:一共n道菜,吃m道,有k个规则,每个菜有自己的价值,每个规则说明吃完X接着吃Y可以额外获得Z个价值。
问可以获得的最大价值是多少。
思路:1<<18保存所有状态,第二维保存最后吃的哪道菜,然后从吃的菜里选一道,从没吃的菜里选一道,吃完X吃Y,
更新dp,判断一下是否当前吃了m道,更新ans便可
#include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <vector> #include <cstdio> #include <string> #include <set> using namespace std; #define inf 0x3f3f3f3f #define maxn 100005 #define sf(x) scanf("%d",&x) #define sf(x,y) scanf("%d%d",&x,&y) #define fre freopen("in.txt","r",stdin) const int M=262150; int v[20],s[20][20]; long long dp[M][20]; int main() { //fre; int n,m,k,x,y,z; long long ans=0; scanf("%d%d%d",&n,&m,&k); memset(s,0,sizeof(s)); memset(dp,0,sizeof(dp)); for(int i=0;i<n;i++) scanf("%d",&v[i]); for(int i=0;i<k;i++) { scanf("%d%d%d",&x,&y,&z); s[x-1][y-1]=z; } for(int i=0;i<n;i++) dp[1<<i][i]=v[i]; int cnt=1<<n; for(int l=0;l<cnt;l++) { int cntt=0; for(int i=0;i<n;i++) { if((l&(1<<i))==0) continue; cntt++; for(int j=0;j<n;j++) { if(l&(1<<j)) continue; int ne=l|(1<<j); dp[ne][j]=max(dp[ne][j],dp[l][i]+v[j]+s[i][j]); } } if(cntt==m) { for(int i=0;i<n;i++) { if(l&(1<<i)) ans=max(ans,dp[l][i]); } } } printf("%lld\n",ans); return 0; }