背包——完全背包Warcraft III(哈理工1053)

本文详细介绍了一道经典的完全背包问题,并提供了完整的代码实现。通过对比01背包和多重背包,阐述了完全背包的特点及其状态转移方程。适用于初学者理解完全背包的概念及解题技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

*不了解01背包的同学请移步  http://blog.youkuaiyun.com/sm9sun/article/details/53235986


题目链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1053

题目描述:

是一道最原始最基本的完全背包题,题意就是魔兽有不同的兵种
他们的攻击力与建造他们的金币都不相同,每个兵种可以无限出。 
开始输入一个t,表示测试t组数据,然后一个g和n,g表示你拥有的金币 
n表示有n个兵种。接下来输入n行数据,每行两个数a[i],b[i]
a[i]表示不同兵种的攻击力,b[i]表示所需的金币 
最后输出总共能获得的最大攻击力 


首先来说明一下完全背包,与多重、01背包不同,完全背包的物品是无限的。那么我们是否可以用多重背包的思路去解决完全背包呢?

我每个物品的取值肯定是有限的,就是总容量/个体容量。那么我就当作是这么多个呗,这个想法可行吗?答案是可行的。

不过我们也不用这么麻烦,每个物品可以取无限次对于我们来说未尝不是好事,因为我们也不用管物品[i]的层次了,他取完我也可以再去

即 我们不用采取dp[i-1][j]构造dp[i][j]的方式,直接遍历所有的重量点即可,加入一个物品n后,每个重量点都看看dp[j-b[i]]+a[i]是否大于原dp[j]

for(i=1;i<=n;i++)     //外层循环依旧是个数 
for(j=b[i];j<=g;j++)   //内层循环依旧是重量,这里是价值 
dp[j]=fmax(dp[j],dp[j-b[i]]+a[i]); 

我们会发现 其实状态转移方程还是和01背包一样~


#include<stdio.h>

int fmax(int a,int b)         //最大值函数 
{
	return a>b?a:b;
}




int main()
{ 
	int i,j,n,g,t;     //控制循环,n兵种数,g钱数,t测试数据 
	int a[10000],b[10000];         //a数组攻击力  b数组所需金币 
	int dp[10000];          //构造动态规划数组 
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&g,&n);          
		for(i=1;i<=n;i++)            
		scanf("%d%d",&a[i],&b[i]);          

        for(i=0;i<=g;i++)    //价值初始化 
        dp[i]=0;  
    
        for(i=1;i<=n;i++)     //外层循环依旧是个数 
		for(j=b[i];j<=g;j++)   //内层循环依旧是重量,这里是价值 
		dp[j]=fmax(dp[j],dp[j-b[i]]+a[i]); 
		
		
		
		/*为什么循环从b[i]开始呢?小于单价的重量点不会受影响*/
        printf("%d\n",dp[g]);
}
return 0;
}
				





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值