Codevs1155 金明的预算方案 ——2006年NOIP全国联赛提高组 变种经典背包dp

来源:互联网 发布:域名注册使用godaddy 编辑:程序博客网 时间:2024/06/05 04:46

Codevs1155 金明的预算方案 ——2006年NOIP全国联赛提高组

由于至多有2个附件,直接手动枚举就好了。
dp时:

  • 如果当前物品是附件, 跳过
  • 如果当前物品时主件
    • 只选这个主件,不选它的附件
    • 当这个主件有附件时, 选它和它的第一个主件
    • 当这个主件有2个附件时, 选它和它的第二个主件
    • 当这个主件有2个附件时, 选它和它的所有附件
#include <cstdio>#include <cstring>#include <iostream>#include <cstdlib>#include <vector>using namespace std;#define MAXN (60+6)#define MAXV (32000+32)struct item{    int v, p, q;}l[MAXN];int dp[MAXV];vector <int> q[MAXN];int main(){    int V, n;    cin >> V >> n;    for(int i = 1; i <= n; i ++)    {        scanf("%d%d%d", &l[i].v, &l[i].p, &l[i].q);        if(l[i].q) q[l[i].q].push_back(i);    }    for(int i = 1; i <= n; i ++)    {        if(l[i].q) continue;        for(int j = V; j >= 0; j --)        {            // 只选主件            if(j >= l[i].v)                dp[j] = max(dp[j], dp[j - l[i].v] + l[i].v*l[i].p);            //只选第一件             if(q[i].size() && j >= l[i].v + l[q[i][0]].v)                dp[j] = max(dp[j], dp[j - (l[i].v + l[q[i][0]].v)] + l[i].v*l[i].p + l[q[i][0]].v*l[q[i][0]].p);            //只选第二件            if(q[i].size() > 1 && j >= l[i].v + l[q[i][1]].v)                dp[j] = max(dp[j], dp[j - (l[i].v + l[q[i][1]].v)] + l[i].v*l[i].p + l[q[i][1]].v*l[q[i][1]].p);            //全选            if(q[i].size() > 1 && j >= l[i].v + l[q[i][0]].v + l[q[i][1]].v)                dp[j] = max(dp[j], dp[j - (l[i].v + l[q[i][0]].v + l[q[i][1]].v)] + l[i].v*l[i].p + l[q[i][0]].v*l[q[i][0]].p + l[q[i][1]].v*l[q[i][1]].p);        }    }    cout << dp[V];    return 0;} 

另:(精简不了多少……)

#include <cstdio>#include <cstring>#include <iostream>#include <cstdlib>#include <vector>using namespace std;#define MAXN (60+6)#define MAXV (32000+32)int dp[MAXV];struct item{    int v, p, q;}l[MAXN];vector <int> q[MAXN];int main(){    int V, n;    cin >> V >> n;    for(int i = 1; i <= n; i ++)    {        scanf("%d%d%d", &l[i].v, &l[i].p, &l[i].q);        if(l[i].q) q[l[i].q].push_back(i);    }    for(int i = 1; i <= n; i ++)    {        if(l[i].q) continue; //如果是附件        for(int j = V; j >= 0; j --)        {            int lson, rson;            if(q[i].size()) lson = q[i][0];// 假设附件为 儿子             if(q[i].size() > 1) rson = q[i][1];            //只选主件            if(j >= l[i].v)                dp[j] = max(dp[j], dp[j-l[i].v] + l[i].v*l[i].p);            //选主件和第一个附件            if(q[i].size() > 0 && j >= l[i].v + l[lson].v)                dp[j] = max(dp[j], dp[j - (l[i].v + l[lson].v)] + l[i].v*l[i].p + l[lson].v*l[lson].p);            //选主件和第二个附件            if(q[i].size() > 1 && j >= l[i].v + l[rson].v)                dp[j] = max(dp[j], dp[j - (l[i].v + l[rson].v)] + l[i].v*l[i].p + l[rson].v*l[rson].p);            //全选            if(q[i].size() > 1 && j >= l[i].v + l[lson].v + l[rson].v)                dp[j] = max(dp[j], dp[j - (l[i].v + l[lson].v + l[rson].v)] + l[i].v*l[i].p + l[lson].v*l[lson].p + l[rson].v*l[rson].p);        }     }    cout << dp[V];    return 0;}
1 0
原创粉丝点击