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