洛谷 P1964【mc生存】买东西

在这里插入图片描述这个题,可以不用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;
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值