*不了解01背包的同学请移步 http://blog.csdn.net/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;}
共同学习,写下你的评论
评论加载中...
作者其他优质文章