Sicily 1346 金明的预算方案

来源:互联网 发布:淘宝客里的返利管理 编辑:程序博客网 时间:2024/05/01 13:08

依赖背包,转为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;}                  


原创粉丝点击