Sicily 1346 金明的预算方案

依赖背包,转为01背包+分组背包

#include <stdio.h>
#include <memory.h>
#include <vector>
using namespace std;
int dp[3220];
struct Item {
    int id;
    int v,p;
};
int n,m;
Item items[70];
vector<Item> add_items[70];
int add_items_dp[70][3220];
int get_max(int a, int b) {
    if (a>b)
        return a;
    else
        return b;
}
void _01_dp() {
    memset(add_items_dp,0,sizeof(add_items_dp));
    int i,j,k;
    Item tmp;

    for (i=1;i<=m;i++) {
        if (items[i].id==0)
            continue;
        for (j=0;j<add_items[i].size();j++) {
            for (k=n-items[i].v;k>=add_items[i][j].v;k--)
                add_items_dp[i][k]=get_max(add_items_dp[i][k], add_items_dp[i][k-add_items[i][j].v]+add_items[i][j].p);
        }
        add_items[i].clear();
        tmp.v=0;
        tmp.p=0;
        //add_items[i].push_back(tmp);
        for (k=n-items[i].v;k>0;k--) {
            if (add_items_dp[i][k]!=add_items_dp[i][k-1]) {
                tmp.v=k;
                tmp.p=add_items_dp[i][k];
                add_items[i].push_back(tmp);
            }
        }
    }
}
void packet_dp() {
    memset(dp,0,sizeof(dp));
    int i,j,k;

    for (i=1;i<=m;i++) {
        if (items[i].id==0)
            continue;
        for (j=n;j>=items[i].v;j--) {
            dp[j]=get_max(dp[j], dp[j-items[i].v]+items[i].p);
            for (k=0;k<add_items[i].size();k++) {
                if (j>=add_items[i][k].v+items[i].v)
                    dp[j]=get_max(dp[j], dp[j-add_items[i][k].v-items[i].v]+add_items[i][k].p+items[i].p);
            }
        }
    }
}
int main() {
    int i;
    int v,p,q;
    Item tmp;

    while (scanf("%d",&n)!=EOF) {
        scanf("%d",&m);
        n=n/10;
        for (i=0;i<70;i++)
            add_items[i].clear();
        for (i=1;i<=m;i++) {
            scanf("%d%d%d",&v,&p,&q);
            if (q==0) {
                items[i].id=i;
                items[i].v=v/10;
                items[i].p=p*v/10;
            }
            else {
                items[i].id=0;
                tmp.v=v/10;
                tmp.p=p*v/10;
                add_items[q].push_back(tmp);
            }
        }
        _01_dp();
        packet_dp();
        printf("%d\n", dp[n]*10);
    }
    return 0;
}                

题目中提到:每个主件最多只有2个附件,所以也可以直接用分组背包解

#include <stdio.h>
#include <vector>
#include <memory.h>
using namespace std;
int n,m;
struct Item {
    int id;
    int v,p;
};
Item items[70];
int dp[3220];
vector<Item> _01_items[70];
vector<Item> add_items[70];
void set_01_items() {
    int i;
    Item tmp;
    for (i=1;i<=m;i++) {
        if (items[i].id==0)
            continue;
        _01_items[i].push_back(items[i]);
        if (add_items[i].size()==1) {
            tmp.v=items[i].v+add_items[i][0].v;
            tmp.p=items[i].p+add_items[i][0].p;
            _01_items[i].push_back(tmp);
        }
        if (add_items[i].size()==2) {
            tmp.v=items[i].v+add_items[i][0].v;
            tmp.p=items[i].p+add_items[i][0].p;
            _01_items[i].push_back(tmp);
            tmp.v=items[i].v+add_items[i][1].v;
            tmp.p=items[i].p+add_items[i][1].p;
            _01_items[i].push_back(tmp);
            tmp.v=items[i].v+add_items[i][0].v+add_items[i][1].v;
            tmp.p=items[i].p+add_items[i][0].p+add_items[i][1].p;
            _01_items[i].push_back(tmp);
        }   
    }
}
int get_max(int a, int b) {
    if (a>b)
        return a;
    else
        return b;
}
int main() {
//  freopen("input.txt", "r", stdin);
//  freopen("output.txt", "w", stdout);
    int i,j,k;
    Item tmp;
    int v,p,q;

    while (scanf("%d",&n)!=EOF) {
        scanf("%d",&m);
        n=n/10;
        for (i=0;i<70;i++) {
            _01_items[i].clear();
            add_items[i].clear();
        }
        for (i=1;i<=m;i++) {
            scanf("%d%d%d",&v,&p,&q);
            if (q!=0) { 
                items[i].id=0;
                tmp.v=v/10;
                tmp.p=p*tmp.v;
                add_items[q].push_back(tmp);
            }
            else {
                items[i].id=i;
                items[i].v=v/10;
                items[i].p=p*items[i].v;
            }
        }
        set_01_items();
        memset(dp,0,sizeof(dp));
        for (i=1;i<=m;i++) {
            if (_01_items[i].size()!=0) {
                for (j=n;j>=0;j--) {
                    for (k=0;k<_01_items[i].size();k++) {
                        if (j>=_01_items[i][k].v)
                        dp[j]=get_max(dp[j], dp[j-_01_items[i][k].v]+_01_items[i][k].p);
                    }
                }
            }
        }
        printf("%d\n", dp[n]*10);
    }
    return 0;
}                  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值