这个题,可以不用dp,毕竟一个格子只能装一种物品。所以贴一个非dp的写法。(小声bb一句,没有测试数据可以下载真的很痛苦啊)
#include<bits/stdc++.h>
using namespace std;
struct Parameters_of_each_item{
int numbers;
int value;
int limit;
string str;
};
struct Parameters_of_each_item array[1000];
int knap(int m,int n)
{
int max_sum=0;int sum2=0;int knap_left;
string temp; int tmp;int j;
for(int i=0;i<21-m;++i)
{
if(i>j) break;
temp=" ";
for(int l=0;l<n;l++)
{
if(array[l].limit==0)//找到还可以背的东西
{knap_left=array[l+1].limit;}
}
max_sum=0;
for( j=0;j<n;++j)
{
if(array[j].limit==0) continue;//这ni行的这种物品已经取完了,直接跳到下一种物品
if(temp==array[j].str)//判断是否有与ni行物品重复的物品nk;
{
if(knap_left>array[j].numbers)//有的话,继续判别背包剩余容量到底还能装多少这个东西
{
knap_left-=array[j].numbers;//装了之后背包容量减小
max_sum=max_sum+(array[j].numbers)*(array[j].value);
}
else
{
max_sum=max_sum+(knap_left)*(array[j].value);//能装满。
}
}
else//遇到不同的物品再进行取舍
{
if(array[j].limit>=array[j].numbers)//完全装得下,就装下和之前的最大值进行比较
{
tmp=max_sum;
max_sum=max(max_sum,(array[j].numbers)*(array[j].value));
if(tmp!=max_sum) //发现取值发生改变
{
knap_left=array[j].limit-array[j].numbers;//背包容量改变
if(tmp!=max_sum) temp=array[j].str;//记录改变物品的名字
}
}
else//装不下,但可以装满
{
tmp=max_sum;
max_sum=max(max_sum,(array[j].limit)*(array[j].value)); //同理
if(tmp!=max_sum) temp=array[j].str;
}
}
}
int sum=0;
for(int k=0;k<n;++k)
{
if(temp==array[k].str)
{sum=array[k].limit; break;}//获得这个格子所选物品的最大限制,也就是这个格子的容量
}
for(int k=0;k<n;++k)
{
if(temp==array[k].str)//我背走的这种物品的参数应该发生改变,包括接下来n-ni行里再次遇到这种物品的处理情况
{
if(array[k].numbers>=sum) {array[k].numbers-=sum;sum=0;}//上一次背走了这个东西的一部分,这是剩余的物品
else {sum-=array[k].numbers; array[k].numbers=0;array[k].limit=0;}//这个东西上一次已经背完了
}
}
sum2+=max_sum;
}
return sum2;
}
int main()
{
int m,n;
cin>>m>>n;
for(int i=0;i<n;++i)
{
cin>>array[i].numbers
>>array[i].value
>>array[i].limit
>>array[i].str;
}
int ans=knap(m,n);
cout<<ans;
return 0;
}