P1064 金明的预算方案

曾经吓死我的背包题

一看就知道是背包啊, 但是不是一般的01背包。

但说到底也就5种决策:

  1. 不取主件

  2. 只取主件,不取任何附件

  3. 取主件,取附件1,不取附件2

  4. 取主件,取附件2,不取附件1

  5. 全都取

按照这5种决策,在她们各自合法的情况下转移即可解决。

代码:

#include<cstdio>
#include<vector>
#include<algorithm>
const int maxn = 65, maxm = 32005;
int dp[maxm];
int v[maxn], p[maxn], q[maxn];
std::vector<int> vec[maxn];
int n, 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]);
        if(q[i]) vec[q[i]].push_back(i);
    }
    for(int i = 1; i <= n; i++)
    {
    	if(q[i]) continue;
        for(int j = m; j >= v[i]; j--)
        {
            dp[j] = std::max(dp[j], dp[j - v[i]] + v[i] * p[i]);
            int siz = vec[i].size();
            if(siz == 1)
            {
                int temp = vec[i][0];
                if(j >= v[i] + v[temp]) dp[j] = std::max(dp[j], dp[j - v[i] - v[temp]] + v[i] * p[i] + v[temp] * p[temp]);
            }
            else if(siz == 2)
            {
                int temp1 = vec[i][0], temp2 = vec[i][1];
                if(j >= v[i] + v[temp1]) dp[j] = std::max(dp[j], dp[j - v[i] - v[temp1]] + v[i] * p[i] + v[temp1] * p[temp1]);
                if(j >= v[i] + v[temp2]) dp[j] = std::max(dp[j], dp[j - v[i] - v[temp2]] + v[i] * p[i] + v[temp2] * p[temp2]);
                if(j >= v[i] + v[temp1] + v[temp2]) dp[j] = std::max(dp[j], dp[j - v[i] - v[temp1] - v[temp2]] + v[i] * p[i] + v[temp1] * p[temp1] + v[temp2] * p[temp2]);
            }
        }
    }
    printf("%d\n", dp[m]);
    return 0;
}
posted @ 2018-11-04 21:12  Garen-Wang  阅读(89)  评论(0编辑  收藏  举报