洛谷P2347 砝码称重

题目描述

设有1g1g1g、2g2g2g、3g3g3g、5g5g5g、10g10g10g、20g20g20g的砝码各若干枚(其总重≤1000 \le 10001000),

输入输出格式

输入格式:

 

输入方式:a1,a2,a3,a4,a5,a6a_1 , a_2 ,a_3 , a_4 , a_5 ,a_6a1,a2,a3,a4,a5,a6

(表示1g1g1g砝码有a1a_1a1个,2g2g2g砝码有a2a_2a2个,…,20g20g20g砝码有a6a_6a6个)

 

输出格式:

 

输出方式:Total=NTotal=NTotal=N

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

 

 

这道题类似于“小A点菜”那道题,都是01背包求方案数

都是先将f[0]=1,然后f[j]+=f[j-c[i]]计算

设f[i][j]为体积为i的方案总和

那么,当第i件物品不选时,f[i][j]=f[i-1][j]

那么如果选择了呢,f[i][j]=f[i-c[i]];

那么两者累加,就是f[i][j]=f[i-1][j]+f[i-c[i]]

为了减少空间浪费,去掉第一维,可以得到:

f[i]=f[i]+f[i-c[i]],也就是f[i]+=f[i-c[i]]

最后再扫一遍记录个数

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define maxn 100010
#define clear(a) memset(a,0,sizeof a)
#define ll long long
#define IL inline
IL void read(int &x)
{
    x = 0;int f = 1;char ch = getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f = -f;ch = getchar();}
    while(ch>='0'&&ch<='9'){x = x * 10 + ch - '0', ch = getchar();}x *= f;
}

int tot, sum, ans;
int pre[7] = {0, 1, 2, 3, 5, 10, 20};
int a[10], f[maxn], val[maxn];

int main()
{
    for (int i = 1; i <= 6;i++)
    {
        read(a[i]);
        sum += a[i]*pre[i];
    }
    f[0] = 1;
    for (int i = 1; i <= 6;i++)
        for (int j = 1;j<=a[i];j++)
            val[++tot] = pre[i];
    for (int i = 1; i <= tot;i++)
        for (int j = sum; j >= val[i];j--)
            f[j] += f[j - val[i]];
    for (int i = 1; i <= sum;i++)
        if(f[i])
            ans++;//如果某一位为true说明可能出现这种情况 
    cout << "Total=" << ans;
    return 0;
}

 

posted @ 2019-02-12 22:28  KGW_源  阅读(257)  评论(0)    收藏  举报
- Hide code