UVA 10154 Weights and Measures(dp)

题意:有几只乌龟,每只乌龟有一定的重量与力量。每只乌龟可以背小于它力量的重量(包括它自身的重量)。问最多一共可以有多少只乌龟叠在一起。

解析:dp[i]表示托i个乌龟时的最轻重量,不断的去更新重量使其最小。
这里要先做好预处理,也就是为最长子序列拍好序。

但是按照什么顺序排序呢?
这里要用到一点贪心,我们想如果现在有两个乌龟,一个力气大,一个力气小,
重力我们先不用管,那么应该把力气大的乌龟放在下面,还是力气小的呢?你可能会想,这和重力有关啊。
仔细分析,如果力量大的在下面,力量小的在上面,那么力量大的还能承受的重力就是
s[大]-w[小]-w[大],力量小的能够承受的重力为s[小],前者可能大于,等于,或小于后者;

如果力量小的在下面,力量大的在上面,
那么力量小的能够承受的重力就是s[小]-w[小]-w[大],
力量大的能够承受的重力为s[大],前者一定小于后者,总的承重能力受制于前者。这两种方式 第二种的总的承重能力显然不及第一种,也就是第一种更优,所以力量大的在下面一定比力量轻的在下面更好。所以我们按力量排序。

因此按照力量升序开始检索,
只要满足tur [i ].s >= tur [i ].w + dp [j ],就可以更新max及dp[j+1],这里更新从大到小是因为我们更新的是dp[j+1],如果从小到大,就破坏的后面的更新。

注意:力量小于本身体重的,连自己都拖不动,是不会被处理的。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 6000;
const int INF =0x3f3f3f3f;
struct Turtle {
	int w,s;
}tur[N];
int dp[N]; //拖i个乌龟的总量
bool cmp(Turtle a,Turtle b) {
	if(a.s != b.s) {
		return a.s < b.s;
	}else {
		return a.w < b.w;
	}
}
int main() {
	int n = 0;
	int w,s;
	while(scanf("%d%d",&w,&s) != EOF) {
		if(w <= s) {
			tur[n].w = w;
			tur[n].s = s;
			n++;
		}
	}
	sort(tur,tur+n,cmp);
	if(n == 0) {
		printf("%d\n",0);
	}else {
		memset(dp,INF,sizeof(dp));
		dp[0] = 0;
		int maxn = 0;
		for(int i = 0; i < n; i++) {
			for(int j = n - 1; j >= 0; j--) {
				if(tur[i].s >= tur[i].w + dp[j] && dp[j+1] > tur[i].w + dp[j]) {
					dp[j+1] = tur[i].w + dp[j];
				}
				if(dp[j+1] != INF)
					maxn = max(j+1,maxn);
			}
		}
		printf("%d\n",maxn);
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值