牛客网 第十四届华中科技大学程序设计竞赛决赛同步赛- Beautiful Land(01背包的逆解法)

链接:https://www.nowcoder.com/acm/contest/119/F
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld

题目描述

It’s universally acknowledged that there’re innumerable trees in the campus of HUST.
Now HUST got a big land whose capacity is C to plant trees. We have n trees which could be plant in it. Each of the trees makes HUST beautiful which determined by the value of the tree. Also each of the trees have an area cost, it means we need to cost c i area of land to plant.
We know the cost and the value of all the trees. Now HUSTers want to maximize the value of trees which are planted in the land. Can you help them?

输入描述:

There are multiple cases.
The first line is an integer T(T≤10), which is the number of test cases.
For each test case, the first line is two number n(1≤n≤100) and C(1≤C≤108), the number of seeds and the capacity of the land. 
Then next n lines, each line contains two integer ci(1≤ci≤106) and vi(1≤vi≤100), the space cost and the value of the i-th tree.

输出描述:

For each case, output one integer which means the max value of the trees that can be plant in the land.
示例1

输入

1
3 10
5 10
5 10
4 12

输出

22

题意:

有一块容量为 C 的土地,现在有 n 棵可供选择的树可以在这块土地上种植,每棵树都需要一定的土地面积,同时自身也有一些价值,现在给出 n 和 C 的值,让你求在这块土地上能得到的最大的价值事多少。


分析:

一看就是01背包的题,但是总是超内存,因为题中的背包容量表面看上去就是这块土地的面积,然而这块土地的面积的范围太大了,开的 dp 也过大,所以一直超内存,仔细看看其实是有别的方法的,树的数量和价值的范围都很小,即使都取最大值,那么最大价值也才10000,故我们可以换个角度想一下,本题就是01背包的一个小变形

我们如果将所给出树的总价值当做背包的容量的话,那么dp数组里存的就是土地的面积,dp[i]表示的是价值和为 i 的树所占的总面积,可想而知,是不是我们要尽可能的将 i 的值变大,将 dp[i] 的值变小,那么我们就要注意不能在初始化 dp 数组时,将其初始化为 0 了,而应该是无穷大,因为我们是逆向求解。当用 01 背包将dp数组更新完之后,我们就要找到在给出的面积上所能得到的最大的价值,必要的步骤代码有注释哦!


#include<algorithm>
#include<stdio.h>
#include<string>
#include<string.h>
#include<math.h>
#include<iostream>
using namespace std;
#define INF 0x3f3f3f3f 
int dp[10005]; 

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n,c;
		int sum=0;
		int v[105],w[105];
		memset(dp,INF,sizeof(dp));///将dp初始为INF,但dp[0]=0 
		dp[0]=0;
		cin>>n>>c;
		for(int i=1;i<=n;i++)
		{
			cin>>w[i]>>v[i];
			sum+=v[i];///统计所有的价值,当做背包的容量 
		}
		for(int i=1;i<=n;i++)///01背包 
		{
			for(int j=sum;j>=v[i];j--)
			{
				dp[j]=min(dp[j],dp[j-v[i]]+w[i]);///这里是取相对小的值 ,同样能得到i的价值,土地使用的越少越好 
			}
		}
		for(int i=sum;i>=0;i--)///从大到小遍历,因为要找到符合土地面积所能得到的最大价值 
		{
			if(dp[i]<=c)
			{
				printf("%d\n",i);
				break;
			}
		}
	}
	return 0;
}













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值