dp - bailian 4141:砝码称重

题目

总时间限制: 1000ms 内存限制: 65536kB
描述
设有1g、2g、3g、5g、10g、20g的砝码各若干枚(其总重<=1000),要求:计算用这些砝码能称出的不同重量的个数,但不包括一个砝码也不用的情况。

输入
一行,包括六个正整数a1,a2,a3,a4,a5,a6,表示1g砝码有a1个,2g砝码有a2个,……,20g砝码有a6个。相邻两个整数之间用单个空格隔开。
输出
以“Total=N”的形式输出,其中N为可以称出的不同重量的个数。
样例输入
1 1 0 0 0 0
样例输出
Total=3
提示
样例给出的砝码可以称出1g,2g,3g三种不同的重量。

分析

状态转移方程是:dp[i][j] = dp[i-1][j] || dp[i-1][j-w[i]], i表示第i个砝码,意思是把所有砝码排开计数,j表示j重量,dp[i][j]表示使用前i个砝码是否可以称出重量j,1表示可以,0表示不可以。
然后可以用滚动数组节省空间,dp[j] = 1 ,当dp[j-w[i]] =1。

代码

#include <cstdio>
#include <cstring>

int weight[6] = {1, 2, 3, 5, 10, 20};
int num[6];
int dp[1000];

int main(){
    for(int i = 0; i < 6; i++){
        scanf("%d", &num[i]);
    }
    int total = 0;
    for(int i = 0; i < 6; i++){
        total += weight[i] * num[i];
    }
    memset(dp, 0, sizeof(dp));
    dp[0] = 1;
    for(int i = 0; i < 6; i++){
        for(int j = 0; j < num[i]; j++){
            for(int k = total; k >= weight[i]; k --){
                if(dp[k - weight[i]] == 1)
                    dp[k] = 1;
            }
        }
    }
    int sum = 0;
    for(int i = 1; i <= total; i++){
        if(dp[i] == 1)
            sum++;
    }
    printf("Total=%d\n", sum);
    return 0;
}
posted @ 2020-04-02 17:12  zhangyue_lala  阅读(329)  评论(0编辑  收藏  举报