多重背包转01背包优化
服务器好好玩。
题目描述
lcy0x1 去服务器的系统商店买东西。
一个人的背包有 21 格。
一开始他的背包里有 m 件不同的物品(不能卖)。
他要买 n 种物品,第 i 件物品的名字为 sti,有 ai 件,价值为 bi,一格可以放 ci 个。
相同的物品可以放同一格(只要没放满)。
问:他跑一次最多能卖多少钱。
输入格式
第一行两个整数 m,n。
下面 n 行,第 i+1 行三个整数 ai,bi,ci 与一个字符串 sti。
输出格式
最多卖的钱 s。
输入输出样例
输入 #1复制
20 3 63 1 64 yinshifen 1 10 1 men 1 1 64 yinshifen
输出 #1复制
64
说明/提示
数据保证:
- 0≤m≤21;
- 0≤n≤100;
- 0≤ai≤1344;
- 0≤bi≤104;
- 0<ci≤64;
- 0<∣sti∣<100;
- 0≤s≤106。
注:数据强大,搜索 0 分,请使用多重背包。
#include<bits/stdc++.h>
using namespace std;
int f[10000];
struct goods{
int piece,price,number,value;
char name[101];
}p [1345];
int m,n;
int main(){
cin>>m>>n;
m=21-m;
for(int i=1;i<=n;i++){
int a,b,c;
cin>>p[i].piece>>p[i].price>>p[i].number>>p[i].name;//结构体输入
for(int j=1;j<=n;j++){
if(i!=j&&strcmp(p[i].name,p[j].name)==0){//如果这次输入的名字和已输入的名字一样(strcmp是判断两个字符串点的差的函数,如果差是0说明相等)
if(p[j].piece+p[i].piece<=p[j].number){//如果两个加起来可以放到一组里
p[j].piece+=p[i].piece;//在之前的那一组里加上去
n--;//总的物品数减一
i--;//将这一组重新输入新的值
break;
}
else {//两个加起来比一组多
p[i].piece=p[i].piece-(p[j].number-p[j].piece);//那么记录多出来的
p[j].piece=p[j].number;//原来的达到最大值
//因为可能有好几组名字相同的,所以这里不能用break结束循环
}
}
}
}
for(int i=1;i<=n;i++){//每一组都算出这一组的价值
p[i].value=p[i].piece*p[i].price;
}
for(int i=1;i<=n;i++){//01背包问题解决
for(int j=m;j>=1;j--){
f[j]=max(f[j],f[j-1]+p[i].value);
}
}
cout<<f[m];//输出
return 0;
}