加了限制条件的动态规划

对于加了限制条件的动态规划,经常需要进行输入数据的预处理

题目:购物单问题====================================================

王强今天很开心,公司发给N元的年终奖。王强决定把年终奖用于购物,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:
主件 附件
电脑 打印机,扫描仪
书柜 图书
书桌 台灯,文具
工作椅
如果要买归类为附件的物品,必须先买该附件所属的主件。每个主件可以有 0 个、 1 个或 2 个附件。附件不再有从属于自己的附件。王强想买的东西很多,为了不超出预算,他把每件物品规定了一个重要度,分为 5 等:用整数 1 5 表示,第 5 等最重要。他还从因特网上查到了每件物品的价格(都是 10 元的整数倍)。他希望在不超过 N 元(可以等于 N 元)的前提下,使每件物品的价格与重要度的乘积的总和最大。
    设第 j 件物品的价格为 v[j] ,重要度为 w[j] ,共选中了 k 件物品,编号依次为 j 1 , j 2 ,……, j k ,则所求的总和为:
v[j 1 ]*w[j 1 ]+v[j 2 ]*w[j 2 ]+ … +v[j k ]*w[j k ] 。(其中 * 为乘号)
    请你帮助王强设计一个满足要求的购物单。
注意:(1)先进行输入数据的预处理。这里重要度没有优先级问题,也就是说没有重要度比较高就先选,而是一个权重问题而已,所以可以设置W=价格x重要度,只需求出最大的W即可。(2)附件的问题。选附件时必须先选择主件,所以这个输入好像是有顺序的。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string.h>
using namespace std;
   
int main(){
    int v[61];  //每件物品的价格
    int vp[61];  //每件物品的价格和重要度的乘积
    int q[61];   //所属附件
    int dp[61][32001];
    int N;
    int m;
    while(cin>>N>>m){
        for(int i=0;i<61;i++){
            memset(dp[i],0,sizeof(dp[i]));
        }
        int impor;
        for(int i=1;i<=m;i++){
            
            cin>>v[i]>>impor>>q[i];
            vp[i]=v[i]*impor;
        }
         
        for(int i=1;i<=m;i++){
            for(int j=1;j<=N;j++){
                if(q[i]==0){
                    if(v[i]<=j){
                        dp[i][j]=max(dp[i-1][j-v[i]]+vp[i],dp[i-1][j]);
                    }
                }
                else{
                    if(v[i]+v[q[i]]<=j){
                        dp[i][j]=max(dp[i-1][j-v[i]]+vp[i],dp[i-1][j]);
                    }
                }
            }
        }
        cout<<dp[m][N]<<endl;
    }
    return 0;
}

这里有个小疑问: 这样会不会造成全部选的都是附件,因为程序并没有在选附件的条件下先选主件,而只是判断(附件+主件的重量)<j。 除非输入的顺序是先输入主件,属于这个主件的附件在这个主件后输入。如果输入顺序是随意的,比如过前10个输入的全是附件,那好像就会造成这个问题。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章