题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3446
题目大意:
题解:
[图截残了orz
状压dp
f[i]表示选了的奶牛去参加比赛的状态为i(二进制表示)的最大得分
知道了i就意味着知道了已经选了多少奶牛参加比赛,即下一个奶牛要参加第几项比赛
又在同一时刻检查的项目先后顺序自定,那么肯定按”门槛“高低,把较低”门槛“的分都拿了,再去看看高门槛的能不能拿啊
[如果还不会就看↓吧orzorzorz]
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<iostream> using namespace std; #define maxn (1<<20)+10 struct node { int k,p,x; }a[30]; int s[30][30],f[maxn]; bool cmp(node x,node y) { if (x.k!=y.k) return x.k<y.k; if (x.p!=y.p) return x.p<y.p; return x.x<y.x; } //int mymax(int x,int y){return (x>y)?x:y;} int main() { //freopen("dec.in","r",stdin); //freopen("dec.out","w",stdout); int n,m,i,j,mx; scanf("%d%d",&n,&m); for (i=1;i<=m;i++) scanf("%d%d%d",&a[i].k,&a[i].p,&a[i].x); sort(a+1,a+1+m,cmp);//排序啊 for (i=1;i<=n;i++) for (j=1;j<=n;j++) scanf("%d",&s[i][j]); memset(f,0,sizeof(f)); mx=(1<<n)-1; for (i=0;i<mx;i++) { int num=1,t=0;//num表示选出来的下一只牛要参加第几项比赛 for (j=1;j<=n;j++) if (i&(1<<j-1)) num++;//已经参加了多少项比赛 for (j=1;j<=m;j++) if (a[j].k==num) {t=j;break;}//t是一个标记 参加完num场比赛的检查项目从哪开始 for (j=1;j<=n;j++) if (!(i&(1<<j-1))) { int jf=0,k=t;//jf表示检查能得到的分(jf=积分233) while (k!=0 && k<=m && a[k].k==num && f[i]+s[j][num]+jf>=a[k].p) {jf+=a[k].x;k++;} if (f[i]+jf+s[j][num]>f[i|(1<<j-1)]) f[i|(1<<j-1)]=f[i]+jf+s[j][num]; //f[i|(1<<j-1)]=mymax(f[i|(1<<j-1)],f[i]+jf+s[j][num]); } } printf("%d ",f[mx]); return 0; }