POJ 1742多重リュック問題

2316 ワード

コイン1個あたりの重量をA[i]とし、数量はC[i]価格はA[i]とする.
dp(i,j)を定義するのは、前のiつの物品が容量jのリュックサックに入れられて得られる最大の価値である.
dp(n,m)を求めるだけです
dp(n,m)を求める過程で、dp(n,1)、dp(n,2)......dp(n,m-1)はすべてすでに求めました
dp(n,i)がiに等しいかどうかを見て、コインでiのものを買うことができるかどうかを判断することができます.
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define MAX_N 100005
#define INF 0x3f3f3f

using namespace std;

typedef long long int ll;
int dp[MAX_N];

int main()
{
    //freopen("1.txt", "r", stdin);


    int weight[MAX_N], value[MAX_N], num[MAX_N];
    int n, m;
    while (cin >> n >> m && n && m)
    {
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &weight[i]);
            value[i] = weight[i];
        }
        for (int i = 1; i <= n; i++)
            scanf("%d", &num[i]);


        memset(dp, 0, sizeof(dp));
        for (int i = 1; i <= n; i++)
        {
            if (weight[i] * num[i] >= m)
            {
                for (int j = weight[i]; j <= m; j++)
                {
                    if (dp[j] < dp[j - weight[i]] + value[i])
                        dp[j] = dp[j - weight[i]] + value[i];
                }
            }
            else
            {
                int k = 1;
                while (k < num[i])
                {
                    for (int j = m; j >= k * weight[i]; j--)
                    {
                        if (dp[j] < dp[j - k * weight[i]] + k * value[i])
                            dp[j] = dp[j - k * weight[i]] + k * value[i];
                    }
                    num[i] -= k;
                    k <<= 1;
                }
                for (int j = m; j >= num[i] * weight[i]; j--)
                {
                    if (dp[j] < dp[j - num[i] * weight[i]] + num[i] * value[i])
                        dp[j] = dp[j - num[i] * weight[i]] + num[i] * value[i];
                }
            }
        }


        int ans = 0;
        for (int i = 1; i <= m; i++)
        {
            if (dp[i] == i)
                ans++;
        }
        printf("%d
", ans); } return 0; }