1. 程式人生 > >【CF580D】Kefa and Dishes

【CF580D】Kefa and Dishes

題目描述

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

第二行是n個數,第i個數表示kefa對第i道菜的滿意度為ai

第三行到第k+2行每行有3個數:xi,yi,ci,表示如果kefa在吃完第xi道菜之後立刻吃了第yi道菜,則會額外獲得ci的滿意度

 

輸出

一行一個數表示最大滿意度


樣例輸入

4 3 2
1 2 3 4
2 1 5
3 4 2


樣例輸出

12

 



題解

狀壓dp。

設dp[ s ][ i ] 表示當前狀態為 s,最後一個吃的菜是 i 獲得的最大滿意度。

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace
std; #define ll long long const int maxn=18+5; const int maxm=(1<<18)+5; ll n,m,k,ad[maxn][maxn],a[maxn]; ll dp[maxm][maxn],cnt,ans; template<typename T>void read(T& aa){ char cc; ll ff;aa=0;cc=getchar();ff=1; while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
if(cc=='-') ff=-1,cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); aa*=ff; } int count(int x){ int ret=0; while(x){ ret++;x&=x-1; } return ret; } int main(){ read(n),read(m),read(k); for(int i=1;i<=n;i++){ read(a[i]); dp[1<<i-1][i]=a[i]; } for(int i=1;i<=k;i++){ ll x,y,z; read(x),read(y),read(z); ad[x][y]=z; } for(int s=0;s<(1<<n);s++){ for(int i=1;i<=n;i++){ if(!(s&(1<<i-1))) continue; for(int j=1;j<=n;j++){ if(j==i||!(s&(1<<j-1))) continue; dp[s][j]=max(dp[s][j],dp[s^(1<<j-1)][i]+a[j]+ad[i][j]); } } } for(int s=0;s<(1<<n);s++) if(count(s)==m){ for(int i=1;i<=n;i++){ if(!(s&(1<<i-1))) continue; ans=max(ans,dp[s][i]); } } cout<<ans<<endl; return 0; }