金明的预算方案【动态规划】

来源:互联网 发布:剑侠情缘手游 淘宝充值 编辑:程序博客网 时间:2024/04/30 15:54

有依赖的01背包问题
方便起见,我们把状态只定义在主件上(对输入进行特殊处理)
每个主件有0,1,2个附件
每次购买时,有五种选择
1.不买
2.只买主件
3.买主件和一号附件
4.买主件和二号附件
5.买主件和全部附件

[i][0]表示主件的价值与花费
[i][1]表示一号附件的价值与花费
[i][2]表示二号附件的价值与花费
当一个物品没有附件时,[i][1]和[i][2]均为0

状态转移方程(只是一个思路方程,不完整!没有写乘上期望值什么的,具体方程请往下看代码)
f(i,j) = max (
f(i-1,j),//不买
f(i-1,j - c[i][0]) + v[i][0],//只买主件
f(i-1,j - c[i][0] - c[i][1]) + v[i][0] + v[i][1],//主件和一号附件
f(i-1,j - c[i][0] - c[i][2]) + v[i][0] + v[i][2],//主件和二号附件
f(i-1,j - c[i][0] - c[i][1] - c[i][2]) + v[i][0] + v[i][1] + v[i][2],//主件和全部附件
)

#include <cstdio>#include <algorithm>int f[72][32010],m,n,c[72][3],v[62][3];int main() {    scanf("%d%d",&n, &m);    for(int i=1; i<=m; i++) {        int w, p, q;        scanf("%d %d %d",&w,&p,&q);        if(q == 0) {            c[i][0] = w;            v[i][0] = p;            continue;        }        if(!v[q][1]) { // 如果第一个附件还没有遇到             c[q][1] = w;            v[q][1] = p;        }        else { //如果已经遇到第一个附件             c[q][2] = w;            v[q][2] = p;        }    }    for(int i=1; i<=m; i++) {        for(int j=10; j<=n; j+=10){            if(j-c[i][0]>= 0) {                f[i][j] = std::max(f[i-1][j],f[i-1][j-c[i][0]] + v[i][0]*c[i][0]);            if(j - c[i][0] - c[i][1] >= 0)                f[i][j] = std::max(f[i][j],f[i-1][j-c[i][0]-c[i][1]] + v[i][1]*c[i][1] + v[i][0]*c[i][0]);              if(j - c[i][0] - c[i][2]>= 0)                f[i][j] = std::max(f[i][j],f[i-1][j-c[i][0]-c[i][2]] + v[i][2]*c[i][2] + v[i][0]*c[i][0]);            if(j-c[i][0] - c[i][1] - c[i][2] >= 0)                f[i][j] = std::max(f[i][j],f[i-1][j-c[i][0]-c[i][1]-c[i][2]] + v[i][2]*c[i][2] + v[i][1]*c[i][1] + v[i][0]*c[i][0]);            }            else                f[i][j] = f[i-1][j];        }    }    printf("%d",f[m][n]);    return 0;}
阅读全文
0 0