DP

来源:互联网 发布:奔驰诊断软件下载 编辑:程序博客网 时间:2024/06/01 10:16

剁手指南

双十一刚过,双十二又快来了。我们熟悉的小明同学准备好好的消费一次,他把购物车塞得满满的,提交订单的时候却发现账户余额不足了,于是他决定放弃一部分物品。要放弃一部分东西是很难的,但是小明同学对自己的评价标准非常有自信,他从头到尾对每个物品做了评价。需要注意的是,物品的评价和价格之间是没有关系的,有些很便宜的物品反而评价很高。他决定将自己全部的账户余额投入到这次购物之中,力求买到的物品的评价之和最高。
你需要写一个程序来计算小明最终买到全部物品的评价之和。
小明的购物车里面所有物品售价均为整数,且以元为单位。
另外,小明还注意到有些店铺是不包邮的,我们认为邮费是整数,以元为单位。认为在同一家店铺购买一件或多件物品时,就会产生固定的邮费。可以认为小明选择的店铺不会很多,在10个以内。(注:得分点1只有一家店铺)

题目中不会出现任何负数。

输入数据:
第一行是两个整数M N,M代表小明选择的店铺数量,N是小明的账户余额。
    接下来有M组数据,其中每组数据:
        第一行是两个整数X Y,X代表小明在这家店铺买的物品数量,Y代表这家店铺的邮费
            接下来X行,每行两个整数A B,A代表物品售价,B代表小明对他的评价

样例输入:
3 100
2 10
20 8
30 9
1 0
40 20
1 10
10 60

样例输出:
89

样例解析:
第一行表示小明的购物车中的物品来自3家店铺,小明有100元的余额
第二行表示第一家店铺有2件物品,店铺邮费10元。
接下来2行,分别代表这两件物品的价格和评价分数
接下来的1 0表示第二家店铺有1件物品,店铺邮费0元(包邮)。
接下来1行,代表这件物品的价格和评分。
接下来的1 10表示第三家店铺有1件物品,店铺邮费10元。
接下来的10 60表示这件物品的价格和评分。

第一家店铺有10元邮费,物品价格为20 30,评价分别为8 9。
第二家包邮,物品价格为40,评价为20。
第三家店铺有10元邮费,物品价格为10,评价为60。
所以第一家店铺买30元的物品+10元邮费,第二家买40元物品,第三家买10元物品+10元邮费,总共100元正好花完。这些物品评价总和为89=9+20+60

得分点1(70分):
输入的M=1。即小明只会从一家店铺购买。
得分点2(30分):
输入的M不为1,每家店铺的邮费不定。

//DP

//求最大评价
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef pair<int,int>PII;
const int maxn=1000+5;
int dp[maxn][maxn];
PII weight[maxn];
int value[maxn];            //价值
bool done[maxn][maxn];                //判断某个商店是否有商品被选中
int store[15];                  //记录店铺的邮费
int main()
{
    int n,w;            //n为店铺数量,w为背包容量
    scanf("%d%d",&n,&w);
    int ans=0;                  //总物品数量
    memset(done,false,sizeof(done));
    int cnt=1;
    while(n--)
    {
        int num,cost;           //物品数量,邮费
        scanf("%d%d",&num,&cost);
        while(num--)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            weight[ans]=PII(cost+a,cnt);                //first储存重量,second储存店铺编号
            value[ans]=b;
            ans++;
        }
        store[cnt]=cost;
        cnt++;
    }
    memset(dp,0,sizeof(dp));
    for(int i=0;i<ans;i++)          //第i+1行决定第i个物品是否购买
        for(int j=0;j<=w;j++)
        {
            int k=weight[i].first;
            int t=weight[i].second;         //当前物品所在的店铺
            bool flag=false;
            for(int m=0;m<i;m++)
                 if(done[m][j]&&weight[m-1].second==t) {
                    flag=true;
                    break;
            }
            int m=k;
            if(flag) m-=store[t];
            if(j<m) {
                    dp[i+1][j]=dp[i][j];
            }
            else {
                dp[i+1][j]=max(dp[i][j],dp[i][j-m]+value[i]);
                if(dp[i+1][j]==dp[i][j]) done[i][j]=false;
                else done[i][j]=true;
            }
        }
    printf("%d\n",dp[ans][w]);
    return 0;
}