【完全背包 && 加和等于 n 的方案数】Alice and Bob

Step1 Problem:

Alice和Bob玩了无数局博弈觉得有点枯燥,于是他们想买一台售价为n元的switch,在switch上一较高下。他们东拼西凑出了m种面额的钱币,每种面额的钱币有无限张,问凑出n元的方案数。
当n=4时,我们认为{1,1,2},{1,2,1},{2,1,1}为同一种方案。
数据范围:
长度不超过 50 位的实数 n (1<=n<= 500), 整数 m (1<=m<=30), 带有一位小数的实数或整数 a[i] (0 <= a[i] <= 50)

Step2 Ideas:

长度不超过 50 位,输入得用字符串。
如果 s 为包含小数点后两位,那么无论如何都构成不了。
然后我们可以对数都乘 10,这样就不存在小数了。
然后就是一个 完全背包,求和 = n 的方案数;

Step3 Code:

#include
using namespace std;
const int MOD = 1e9+7;
int v[50], dp[6000];
int main()
{
    int n, m;
    char s[100];
    while(~scanf("%s %d", s, &m))
    {
        double x;
        for(int i = 0; i < m; i++)
        {
            scanf("%lf", &x);
            v[i] = x*10;
        }
        int len = strlen(s);
        int flag = 0, num = 0;
        for(int i = 0; i < len; i++)
        {
            if(flag) num++;
            if(s[i] == '.') flag = 1;
        }
        if(num >= 2) {
            printf("0\n");
            continue;
        }
        else {
            n = 0;
            for(int i = 0; i < len; i++)
            {
                if(s[i] == '.') continue;
                n = n*10 + s[i] - '0';
            }
            if(num == 0) n *= 10;
            memset(dp, 0, sizeof(dp));
            dp[0] = 1;
            for(int i = 0; i < m; i++)
            {
                for(int j = v[i]; j <= n; j++)//完全背包
                {
                    dp[j] += dp[j-v[i]];
                    dp[j] %= MOD;
                }
            }
            printf("%d\n", dp[n]);
        }
    }
    return 0;
}

你可能感兴趣的:(比赛卡住题,动态规划(DP)背包问题)