博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【t067】补充装备
阅读量:5316 次
发布时间:2019-06-14

本文共 2144 字,大约阅读时间需要 7 分钟。

Time Limit: 1 second

Memory Limit: 128 MB

【问题描述】

Mini进入洞口前自然要先来到镇里的装备店买些装备。买每件装备都需要付出一定的体力点,同时也会获得一定的能力点(每种装备
都可以买无限次^_^,但人的体力点可是有限的哦^_^)。当同种装备挑选的数量>=5时,除了挑选这些物品所获得的能力点之外
还会获得额外的Q*K(K表示挑选的数量)点的能力点。但是,同样的,Mini也会付出更多的体力点,即体力点还将多付出Q*K(K
表示挑选的数量)点。挑选的物品越多,产生的力量就越大,体力点也会付出越多。不过,这额外获得的能力点和付出的体
力点是可以不要的。为了能获得最大的能力点,同时也不至于使自己过分劳累(体力恰好为0不算过分劳累),Mini应该如何购
买装备呢?

【输入格式】

第一行,两个数N和M,N表示有多少种装备,0<=N<=340,每种装备可以买无限次。M表示Mini所拥有的体力点数,0<=M<=500。
以下N行,第I行三个数, WI,QI,Q。WI表示买第I个装备所付出的体力点,QI表示买第I个装备能获得的能力点,Q表示当第I个装备
的数量>=5时所产生的共鸣点。1<=WI<=9000,0<=QI<=9000,0<=Q<=9000。

【输出格式】

一个数,表示在保证Mini不会过分劳累的情况下所能买到的最大能力点

Sample Input

5 8735 48 73 57 645 9 243 4 05 7 7

Sample Output

1653
 

【题解】

这题比较烦的地方是,多出来的额外能力点。但是其有说,如果不想要的话,可以不用花费额外的体力获得额外的技能点。也就是说。我可以买一个东西买了6个,但是不消耗额外体力获得5*q+6*q能力点的情况是允许的。

考虑到这种情况。我们先不要管那些额外技能点。

先按照给出的w[i],c[i]进行完全背包的操作。

会有两层for

for i 和for j

j是容量。

然后我们不能等这两层循环都结束之后再去处理额外能力点的问题。而应该在i层循环中一边处理不考虑额外能力点的完全背包问题一边在完全背包结束后考虑额外能力点的问题。

因为额外能力点也是一个完全背包。所以其更新方式也是顺序更新。

同时在不考虑额外能力点的完全背包中。要记录f[j]对应的num[j],即f[j]是在买了几个装备后获得的值。然后在单独考虑额外能力点的完全背包中。我们同样枚举j,只有在num[j] >=4的时候才尝试更新,即如果num[j] >=4 则看一下ju = j + (num[j]+1)*q[i] 是否大于m,如果不大于,则查看

f[j+(num[j]+1)*q[i]] 和 f[j] + (num[j]+1)*q[i]的大小关系。如果前者小于后者,则更新前者。

同时修改num[j+(num[j]+1)*q[i]]的值为num[j]+1;

因为是以j为更新起点,所以是num[j] >=4,因为再买一个装备就变成5了。

这段题解可以根据代码来理解。

【代码】

#include 
#include 
int n,m,w[400],c[400],q[400],f[600] = {0},num[600] = {0};int main(){	//freopen("F:\\rush.txt","r",stdin);	scanf("%d%d",&n,&m);	for (int i = 1;i <= n;i++)		scanf("%d%d%d",&w[i],&c[i],&q[i]);	for (int i = 1;i <= n;i++)		{
			memset(num,sizeof(num),0);			for (int j = w[i];j <= m;j++) //先进行一次完全背包 不考虑多出来的额外技能点 				if (f[j] < f[j-w[i]] + c[i])					{						f[j] = f[j-w[i]] + c[i];						num[j] = num[j-w[i]] + 1;					}			for (int j = 0;j <= m;j++) //考虑额外技能点,因为也是完全背包所以顺序枚举 				if (num[j] >= 4) //如果数目大于等于4再更新一个装备就能>=5了 					{						int ju = j+(num[j]+1) * q[i]; //这是所需要的花费 						if (ju > m) continue;						if (f[ju] < f[j] + q[i] * (num[j]+1)) 							{								f[ju] = f[j] + q[i] * (num[j]+1); //加上相应的价值 看看是否更优 								num[ju] = num[j] + 1;	//同时要更新数目 							}					}		}	printf("%d",f[m]);	return 0;}

转载于:https://www.cnblogs.com/AWCXV/p/7632369.html

你可能感兴趣的文章
原百万访问量博客http://blog.chinaunix.net/uid/20656672.html不再维护(10年前数百篇oracle/teradata性能优化、故障处理案例)...
查看>>
redis入门
查看>>
(转帖)对抽象编程:接口和抽象类
查看>>
spring boot中servlet启动原理
查看>>
Linux添加用户(user)到用户组(group)
查看>>
一个技术人的知识管理方法论
查看>>
ionic 中文 API CSS and javascript link
查看>>
LINUX IRC使用
查看>>
C#中二进制和流之间的各种相互转换
查看>>
项目总结
查看>>
【Android Studio安装部署系列】十三、Android studio添加和删除Module 2
查看>>
Cordova入门系列(三)Cordova插件调用 转发 https://www.cnblogs.com/lishuxue/p/6018416.html...
查看>>
jQuery遍历not的用法
查看>>
JS获取本周、本季度、本月、上月的开端日期、停止日期
查看>>
Mealy状态机的一点理解
查看>>
Python第一天学习---基础语法
查看>>
Android 应用程序窗体显示状态操作(requestWindowFeature()的应用)
查看>>
PHP实现微信随机红包算法和微信红包的架构设计简介
查看>>
Could not find result map
查看>>
Git Bash的一些命令和配置
查看>>