洛谷P2347 砝码称重 【多重背包】

题目链接:https://www.luogu.org/problemnew/show/P2347

题目描述

设有1g、2g、3g、5g、10g、20g的砝码各若干枚(其总重<=1000),

输入输出格式

输入格式:

输入方式:a1 a2 a3 a4 a5 a6

(表示1g砝码有a1个,2g砝码有a2个,…,20g砝码有a6个)

输出格式:

输出方式:Total=N

(N表示用这些砝码能称出的不同重量的个数,但不包括一个砝码也不用的情况)

输入输出样例

输入样例#1:
1 1 0 0 0 0
输出样例#1:
Total=3

解题思路:

先打一个b[10]={0,1,2,3,5,10,20};再用a数组记录展开后的a1个1g,a2个2g。。将多重背包转化为01背包问题

举个栗子:2 1 2 1 1 1存在a里就是1 1 2 3 3 5 10 20 ;

a数组里元素个数为a1~a6的和,记为num

从1到num扫一遍,把所有可能出现的情况在一个f数组中标记出来;

最后从1000到0跑一遍,找到的一个非零的值ans++;跑完之后ans即为所有情况数;

 
#include<bits/stdc++.h>
using namespace std;
bool f[1001];          //f数组存放第k+w[i]种重量有没有被称出来过
int a[7], w[] = { 0,1,2,3,5,10,20 };
int main() {
    for (int i = 1; i <= 6; i++)
        scanf("%d", &a[i]);
    memset(f, 0, sizeof(f));
    f[0] = 1;   //这个初始化非常重要
    for (int i = 1; i <= 6; i++)         //对砝码的种类进行枚举
        for (int j = 1; j <= a[i]; j++) // 每一种相同质量的砝码个数进行枚举
            for (int k = 1000; k >= 0; k--) { //k表示当前重量
                if (f[k] && k + w[i] <= 1000)
                    f[k + w[i]] = 1;      //如果第k+w[i]个没有称出来过就标记上
            }
    int ans = 0;
    for (int i = 1; i <= 1000; i++)  //注意这里从1开始,因为题目要求不包含一个砝码也不用的情况
    {
        if (f[i]) ans++;
    }
    printf("Total=%d", ans); 
    return 0;
}
 
  
2018-05-14

猜你喜欢

转载自www.cnblogs.com/00isok/p/9037800.html