bzoj3446[Usaco2014 Feb]Cow Decathlon全能奶牛

题目链接: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;
}


转载于:https://www.cnblogs.com/Euryale-Rose/p/6527847.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值