Codeforces ----- Kefa and Dishes [状压dp]
题目大意:给你n道菜以及每道菜一个权值,k个条件,即第y道菜在第x道后马上吃有z的附加值,求从中取m道菜的最大权值
看到这道题,我们会想到去枚举,但是很显然这是会超时的,再一看数据范围,n只有18,那么我们就可以用状压去做了,dp数组也还是比较好定义的,dp[i][state]表示现在吃到第i道菜状态为state的最大权值,既然有k个限制条件我们就按每个菜去扩展,然后就是一个裸的状压dp了,记得要开long long
#include<iostream> #include<cstdio> #include<cmath> #include<string> #include<cstring> #define in(i) (i=read()) using namespace std; typedef long long lol; lol read() { lol ans=0,f=1; char i=getchar(); while(i<'0'||i>'9') { if(i=='-') f=-1; i=getchar(); } while(i>='0'&&i<='9') { ans=(ans<<1)+(ans<<3)+i-'0'; i=getchar(); } return ans*f; } lol dp[19][1<<18]; lol a[19],b[19][19]; lol n,m,k; int main() { lol ans=0; in(n);in(m);in(k); for(lol i=1;i<=n;i++) in(a[i]); for(lol i=1;i<=k;i++) { lol u,v,c; in(u);in(v);in(c); b[u][v]=c; } for(lol i=1;i<=n;i++) dp[i][1<<i-1]=a[i]; for(lol i=0;i<(1<<n);i++) { lol cnt=0; for(lol j=1;j<=n;j++) { if(i&(1<<(j-1))) { cnt++;//这里的cnt是已经经过前面的if的语句,也就是说这里的cnt是看此状态有多少位是1,也就是会吃多少道菜,所以才有了下面的if(cnt==m)这个语句 for(lol k=1;k<=n;k++) { if(!(i&(1<<k-1))) { dp[k][i|(1<<k-1)]=max(dp[k][i|(1<<k-1)],dp[j][i]+a[k]+b[j][k]); } } } } if(cnt==m) { for(lol j=1;j<=n;j++) if(i&(1<<(j-1)))//一定要记得判断 ans=max(ans,dp[j][i]); } } cout<<ans<<endl; return 0; }
博主蒟蒻,随意转载.但必须附上原文链接
http://www.cnblogs.com/real-l/
http://www.cnblogs.com/real-l/