[JOISC2014]挂饰

[JOISC2014]挂饰
难度:提高+/省选-
分类:动态规划,01背包,贪心,剪枝
分析:初看这道动态规划题,可以看出是一道01背包题,但这道题不同于其他01背包的地方在于挂钩的问题,其挂钩数量如果少于后面挂饰挂钩的数量,便会多次挂上却没有意义,于是我们可以设置一个结构体,将结构体按照挂钩数量从大到小排序,保证先算挂钩数量多的,让后按照01背包模板打上去就可以了,但要注意下表小于0的情况,就把这个挂件扔到手机上就行了,于是可得转移方程:
dp[i][j] = max(dp[i - 1][j],dp[i - 1][max(j - c[i].a,0) + 1] + c[i].b)
注意要先将dp数组赋为极小值,起始状态为dp[0][1] = 0
目标:max(dp[n][i])

code
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int n,dp[5][2005],ans;//可用滚动数组优化
struct node{
	int a,b;//a表示挂钩数量,b表示喜悦值
}c[2005];
bool cmp(const node &x,const node &y) {
	return x.a > y.a;//按照挂钩数量从小到大排序
}
int main() {
	scanf("%d",&n);
	for(int i = 1;i <= n;i ++)
	scanf("%d %d",&c[i].a,&c[i].b);
	sort(c + 1,c + n + 1,cmp);
	memset(dp,-0x3f3f3f3f,sizeof(dp));//极小值
	dp[0][1] = 0;//初始状态
	for(int i = 1;i <= n;i ++) {
		for(int j = 0;j <= n;j ++) {
			dp[i & 1][j] = max(dp[(i - 1) & 1][j],dp[(i - 1) & 1][max(j - c[i].a,0) + 1] + c[i].b);//dp方程
		}
	}
	ans = -0x3f3f3f3f;
	for(int i = 0;i <= n;i ++)
	ans = max(ans,dp[n & 1][i]);//答案
	printf("%d\n",ans);
	return 0;
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值