NYOJ289苹果

描述

ctest有n个苹果,要将它放入容量为v的背包。给出第i个苹果的大小和价钱,求出能放入背包的苹果的总价钱最大值。


输入
有多组测试数据,每组测试数据第一行为2个正整数,分别代表苹果的个数n和背包的容量v,n、v同时为0时结束测试,此时不输出。接下来的n行,每行2个正整数,用空格隔开,分别代表苹果的大小c和价钱w。所有输入数字的范围大于等于0,小于等于1000。
输出
对每组测试数据输出一个整数,代表能放入背包的苹果的总价值。
样例输入
3 3
1 1
2 1
3 1
0 0
样例输出

2


**看完这到题,有三种思路,1,贪心,2,深搜(dfs),3,动态规划,没学动态规划的一定会优先考虑前两种方法,结果:贪心WA,深搜超时

1,贪心思路,按单位价值排序,然后从大到小谈,但是有有特殊情况

例如

5 5

1 1

2 2

3 3

4 4

5 5

当单位价值一样的时候,他会输出3...而这种情况下就要逼我们去遍历一遍,再做选择,当然你也可以多级排序什么的,我觉的太麻烦就跳过了,而且加了判断特殊情况后还超时了

下面是我的贪心代码(cin相当于scanf,cout相当与printf,>> << 表示要读入和输出的内容,其他都是c的东西)

#include <iostream>
#include <algorithm>
using namespace std;
struct Node{
	double c;
	double w;
	double val;
};
Node apple[1010];
int compare(Node a,Node b)
{
	return a.val > b.val;
}
int main()
{
	int n,v;
	while(cin>>n>>v && n!=0 && v!=0)
	{
		int i,sum;
		for(i=0;i<n;i++)
		{
			cin>>apple[i].c>>apple[i].w;
			apple[i].val = apple[i].w/apple[i].c;
		}
		sort(apple,apple+n,compare);
		
		for(i=0;i<n;i++)
		{
			cout<<apple[i].c<<" "<<apple[i].w<<" "<<apple[i].val<<endl;
		}
		i = 0;
		sum = 0;
		while(v>=apple[i].c)
		{
			sum += apple[i].w;
			v -=apple[i].c;
			i++;
		}
		cout<<sum<<endl;
	}
}


2,深搜的思路,从头开始遍历,每一个苹果有两种情况,放或者不放,遍历所以情况,输出结果

#include <iostream>
using namespace std;
int n,v;
int c[1010];
int w[1010];
int themax;
void dfs(int x,int t,int sum)//x表示第几个苹果,t表示当前可以装的最大体积,sum表示当前的价值 
{
	if(x==n)//出口 
		return ;
	if(sum>themax)//更新最大值 
		themax = sum;
	
	dfs(x+1,t,sum);//跳过当前苹果 
	dfs(x+1,t-c[x],sum+w[x]);//放入当前苹果 
}
int main()
{
	while(cin>>n>>v && n!=0 && v!=0)
	{
		for(int i=0;i<n;i++)
		{
			cin>>c[i]>>w[i];
			themax = 0;	
		}
			dfs(0,v,0);
			cout<<themax<<endl;
	}
	return 0;
}

3.就是正解dp的方法了,

很多人不明白的就是

if(j<c[i])
dp[i+1][j] = dp[i][j];
else
dp[i+1][j] = max(dp[i][j],dp[i][j-c[i]]+w[i]);

这不是随随便便就写的,而是动态规划转移方程,通过推到才出来的,网上有好多讲这个的东西,多看看别人的博客,看懂为至,毕竟我菜,也说不清到不明,下面是代码

#include <iostream>
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;
int c[1010];
int w[1010];
int dp[1010][1010];
int main()
{
	int n,v;
	while(cin>>n>>v && n!=0 && v!=0)
	{
		for(int i=0;i<n;i++)
			cin>>c[i]>>w[i];
		for(int i=0;i<=n;i++)
		{
			for(int j=0;j<=v;j++)
			{
				if(j<c[i])//如果当前的放不下
					dp[i+1][j] = dp[i][j];//跳过当前
				else
					dp[i+1][j] = max(dp[i][j],dp[i][j-c[i]]+w[i]);//选择前两种方法(上一步的结果)中的较大值(放或不放)
			}
		}
		
		cout<<dp[n][v]<<endl;
	}
	return 0;
}

奈何我冒泡的算法如果打动你超时的心!!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值