暑假- 动态规划 I-(U - Space Elevator)

/*
题意:给出K种石头,每种石头有(高度,此种石头的最大高度,数量),求出能搭建的最高的高度。
思路:多重背包,多了一个限制条件:最大高度。因为每种石头都有着最大高度,所以应该优先处理
最大高度值越低的石头类型(不然一会处理完其他石头时,高度已经超过某些最大高度值较小的石头了)
*/
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
struct Node
{
	int h;//高度
	int a;//最大高度
	int c;//数量
};
int dp[40005];
bool cmp(Node b,Node d)
{
	return b.a<d.a;
}
int mymax(int a,int b)
{
	return a>b?a:b;
}
int main()
{
	int k,maxsum=0;
	Node block[405];
	cin>>k;
	memset(dp,0,sizeof(dp));
	for(int i=0;i<k;i++)
	{
		cin>>block[i].h;
		cin>>block[i].a;
		cin>>block[i].c;
	}
	sort(block,block+k,cmp);
	for(int i=0;i<k;i++)
	{
		if(block[i].h*block[i].c>=block[i].a)//价值*数量>=背包容量,
		{                                    //相当于有无数件可用。(完全背包)
			for(int j=block[i].h;j<=block[i].a;j++)//完全背包(顺序)
			{
				dp[j]=mymax(dp[j],dp[j-block[i].h]+block[i].h);
			}
		}
		else//否则用01背包求解(二进制优化)
		{
			int k=1,c=block[i].c;
			while(c-k>0)
			{
				for(int j=block[i].a;(j>=block[i].h*k);j--)//01背包(逆序)
				{
					dp[j]=mymax(dp[j],dp[j-(block[i].h)*k]+(block[i].h)*k);
				}
				c-=k;
				k*=2;//二进制优化
			}
			for(int j=block[i].a;(j>=block[i].h*c);j--)
			{
				dp[j]=mymax(dp[j],dp[j-(block[i].h)*c]+(block[i].h)*c);
			}
		}
	}
	for(int i=0;i<=block[k-1].a;i++)//遍历求出最大值。
	{
		if(maxsum<dp[i])
		{
			maxsum=dp[i];
		}
	}
	cout<<maxsum<<endl;
	return 0;
}

你可能感兴趣的:(dp)