洛谷p1064 金明的预算方法

附带条件01背包问题
本文介绍了一种特殊的01背包问题,即当选择某个物品时还可能需要选择其对应的附件。文章详细阐述了解决该问题的算法,并通过代码示例展示了具体的实现过程。

有附带条件的01背包

要那附件必须拿主件

因为一个主件最多有两个附件,所以每次遇到主件可能有四种选择

1、只拿主件

2、拿主件和一号附件

3、拿主件和二号附件

4、都拿

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;

const int MAXV = 32005;
const int MAXN = 65;

int dp[MAXV];
int p[MAXN], q[MAXN], v[MAXN];
int N, M;

void slv()
{
    memset(dp, 0, sizeof(dp));
    bool k1, k2;
    int t1, t2;

    for(int i = 1; i <= N; i++)
    {
        t1 = t2 = 0;
        k1 = k2 = false;
        if(q[i] == 0)
        {
            k1 = k2 = false;
            for(int k = i+1; k <= N; k++)
            {
                if(q[k] == i)
                {
                    t1 = k;
                    k1 = true;
                    break;
                }
            }

            for(int k = t1+1; k <= N; k++)
            {
                if(q[k] == i)
                {
                    t2 = k;
                    k2 = true;
                    break;
                }
            }

            for(int s = M; s >= v[i]; s--)
            {
                dp[s] = max(dp[s], dp[s-v[i]] + v[i]*p[i]);

                if(s-v[i]-v[t1] >= 0 && k1)
                {
                    dp[s] = max(dp[s], dp[s-v[i]-v[t1]] + v[i]*p[i] + v[t1]*p[t1]);
                }
                if(s-v[i]-v[t2] >= 0 && k2)
                {
                    dp[s] = max(dp[s], dp[s-v[i]-v[t2]] + v[i]*p[i] + v[t2]*p[t2]);
                }
                if(s-v[i]-v[t1]-v[t2] >= 0 && k1 && k2)
                {
                    dp[s] = max(dp[s], dp[s-v[i]-v[t1]-v[t2]] + v[i]*p[i] + v[t1]*p[t1] + v[t2]*p[t2]);
                }
            }
        }
    }

    printf("%d\n", dp[M]);

}

int main()
{
    scanf("%d%d", &M, &N);

    for(int i = 1; i <= N; i++)
        scanf("%d%d%d", &v[i], &p[i], &q[i]);

    slv();

    return 0;
}

 

转载于:https://www.cnblogs.com/ymzjj/p/9147657.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值