急!灾区的食物依然短缺!
为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品,其价格不等,并且只能整袋购买。
请问:你用有限的资金最多能采购多少公斤粮食呢?
后记:
人生是一个充满了变数的生命过程,天灾、人祸、病痛是我们生命历程中不可预知的威胁。
月有阴晴圆缺,人有旦夕祸福,未来对于我们而言是一个未知数。那么,我们要做的就应该是珍惜现在,感恩生活——
感谢父母,他们给予我们生命,抚养我们成人;
感谢老师,他们授给我们知识,教我们做人
感谢朋友,他们让我们感受到世界的温暖;
感谢对手,他们令我们不断进取、努力。
同样,我们也要感谢痛苦与艰辛带给我们的财富~
为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品,其价格不等,并且只能整袋购买。
请问:你用有限的资金最多能采购多少公斤粮食呢?
后记:
人生是一个充满了变数的生命过程,天灾、人祸、病痛是我们生命历程中不可预知的威胁。
月有阴晴圆缺,人有旦夕祸福,未来对于我们而言是一个未知数。那么,我们要做的就应该是珍惜现在,感恩生活——
感谢父母,他们给予我们生命,抚养我们成人;
感谢老师,他们授给我们知识,教我们做人
感谢朋友,他们让我们感受到世界的温暖;
感谢对手,他们令我们不断进取、努力。
同样,我们也要感谢痛苦与艰辛带给我们的财富~

Input
输入数据首先包含一个正整数C,表示有C组测试用例,每组测试用例的第一行是两个整数n和m(1<=n<=100, 1<=m<=100),分别表示经费的金额和大米的种类,然后是m行数据,每行包含3个数p,h和c(1<=p<=20,1<=h<=200,1<=c<=20),分别表示每袋的价格、每袋的重量以及对应种类大米的袋数。
Output
对于每组测试数据,请输出能够购买大米的最多重量,你可以假设经费买不光所有的大米,并且经费你可以不用完。每个实例的输出占一行。
Sample Input
1 8 2 2 100 4 4 100 2
Sample Output
400
方法一:循环输入并判断n个物品,最外圈循环该物品的数量,然后判断是加入该物品还是不加入更合理,如果判断的所有价格中都是不选更合理,就不用再循环物品的下一个数目,直接数目循环,然后开始第二个物品的数目循环
代码如下
#include #include #include #define maxn 110 int pay,n; int dp[maxn]; using namespace std; int main() { int c; while(~scanf("%d", &c)) { while(c--) { memset(dp, 0, sizeof(dp)); scanf("%d%d", &pay, &n); //种类 for(int i = 0; i < n; i++) { int p, w, m; scanf("%d%d%d", &p, &w, &m); //数目 for(int j = 0; j < m; j++) { int bk = 1; //金额 for(int k = pay; k >= p; k--) { if(dp[k] < dp[k - p] + w) { dp[k]= dp[k - p] + w; bk = 0; } } if(bk) break; } } printf("%d\n",dp[pay]); } } return 0; }
方法二=.=:大神总是厉害的,利用二进制来简便算法!!!同样是循环数目,数目增加按照2的n次方进行增加,如果2的零次方和一次方都选了就是3=.=,详细看代码#include #include #define maxn 110 int n, pay, f[maxn]; using namespace std; bool make(int pi,int wi){ bool bk = 1; //=.=第一次金额由pay循环到p * 1,重量为w * 1 //第二次金额由pay循环到p * 2,重量为w * 2 //啊啊啊!!是不是循环第一次选择了循环第二次也选择了 //额,就变成了选择了三个(┬_┬) //第三次金额由pay循环到p * 4,重量为w * 4 for(int j = pay; j >= pi; --j) { if(f[j] < f[j - pi] + wi) { f[j] = f[j - pi] + wi; bk = 0; } } return bk; } int main() { int c; while(~scanf("%d", &c)) { while(c--) { scanf("%d%d", &pay, &n); for(int i = 0; i <= pay; ++i) f[i] = 0; for(int i = 1; i <= n; ++i) { int p, w , m; scanf("%d%d%d", &p, &w, &m); int t = 1; bool bo = 0; while(t <= m) { //如果当前加入的个数在所有金额循环中都是不取更高 //那么就不必再循环加入更多的此物品 bo = make(t * p, t * w); if(bo) break; m -= t;//第一次循环:m - 1 //第二次过来,m - 1 - 2 //第三次过来m - 1 - 2 - 4 //为啥m也减呢??? //m 所减的总数是当前次t的值 //即执行完下一步以后的t值 //那个while条件就是当循环一半m数目的时候 //然后最后一次执行以后所有的次数执行为m或者m - 1; t *= 2;//咩咩咩?? //第一次循环:t = 2 //第二次:t = 4; //利用二进制!!! } //最后的bo都是不插入当前元素所得重量更大,就没必要再循环下面插入m的操作 if(bo) continue; if(m) make(m * p, m * w); } printf("%d\n", f[pay]); } } return 0; }