题意:有几只乌龟,每只乌龟有一定的重量与力量。每只乌龟可以背小于它力量的重量(包括它自身的重量)。问最多一共可以有多少只乌龟叠在一起。
解析: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],如果从小到大,就破坏的后面的更新。
注意:力量小于本身体重的,连自己都拖不动,是不会被处理的。
解析: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;
}