题目链接: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\n",f[mx]);
return 0;
}