1. 程式人生 > >Codeforces 580D Kefa and Dishes(狀態壓縮DP)

Codeforces 580D Kefa and Dishes(狀態壓縮DP)

直接 a+b code 組成 star using ios AI ret

題目鏈接:http://codeforces.com/problemset/problem/580/D

題目大意:
有n盤菜每個菜都有一個滿意度,k個規則,每個規則由x y c組成,表示如果再y之前吃x那麽滿意度會額外增加c,
現在凱迪想吃m盤菜,並且滿意度最大,請求出滿意度。
解題思路:
狀壓DP,設dp[i][j]表示在狀態i並且最後一道菜放在位置j時的最大滿意度。
註意要處理好一道菜時的情況,以及註意二進制表示中1的個數超過m的情況。

代碼:

 1 #include<bits/stdc++.h>
 2 #define lc(a) (a<<1)
 3 #define rc(a) (a<<1|1)
 4
#define MID(a,b) ((a+b)>>1) 5 #define fin(name) freopen(name,"r",stdin) 6 #define fout(name) freopen(name,"w",stdout) 7 #define clr(arr,val) memset(arr,val,sizeof(arr)) 8 #define _for(i,start,end) for(int i=start;i<=end;i++) 9 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0); 10
using namespace std; 11 typedef long long LL; 12 const int N=25; 13 const int INF=0x3f3f3f3f; 14 const double eps=1e-10; 15 16 LL ans,n,m,p; 17 LL val[N],mp[N][N],dp[1<<18][N];//dp[i][j]表示i的狀態下最後一個盤子選擇第j個的最優解 18 19 int main(){ 20 FAST_IO; 21 cin>>n>>m>>p; 22
for(int i=0;i<n;i++){ 23 cin>>val[i]; 24 } 25 for(int i=1;i<=p;i++){ 26 int x,y,c; 27 cin>>x>>y>>c; 28 mp[x-1][y-1]=c; 29 } 30 memset(dp,-1,sizeof(dp)); 31 ans=0; 32 int lim=(1<<n); 33 for(int i=1;i<lim;i++){ 34 int cnt=0; 35 for(int j=0;j<n;j++){ 36 int tmp=(1<<j); 37 if(tmp&i) 38 cnt++; 39 } 40 //點菜數不能>m 41 if(cnt>m) continue; 42 for(int j=0;j<n;j++){ 43 int tmp=(1<<j); 44 if(tmp&i){ 45 int pre=i-tmp; 46 //單個菜的時候沒有前一個菜所以直接賦值,否則會被0 x類型的rule影響 47 if(cnt==1) 48 dp[i][j]=val[j]; 49 else{ 50 for(int k=0;k<n;k++){ 51 if(dp[pre][k]==-1) continue; 52 dp[i][j]=max(dp[i][j],dp[pre][k]+mp[k][j]+val[j]); 53 } 54 } 55 ans=max(dp[i][j],ans); 56 } 57 } 58 } 59 cout<<ans<<endl; 60 return 0; 61 }

Codeforces 580D Kefa and Dishes(狀態壓縮DP)