UVA 10154 - Weights and Measures

这道题隔了一个才做,动归有些生疏了,但从新捡起来发现比以前理解的更透彻了。

f[i]表示托i个乌龟时的最轻重量,不断的去更新重量使其最小。

这里要先做好预处理, 也就是为最长子序列拍好序。但是按照什么顺序排序呢?这里要用到一点贪心,我们想如果现在有两个乌龟,一个力气大一个力气小,重力我们不用管,那么应该把力气大的乌龟放在下面,还是力气小的呢,你可能会想,这和重力有关啊,仔细分析,如果力量大的在下面,力量小的在上面,那么力量大的还能承受的重力就是s[da]-w[xiao]-w[da],力量小的能够承受的重力为s[xiao],前者可能大于,等于,或小于后者;如果力量小的在下面,力量大的在上面,那么力量小的能够承受的重力就是s[xiao]-w[xiao]-w[da],力量大的能够承受的重力为s[da],前者一定小于后者,总的承重能力受制于前者。这两种方式 第二种的总的承重能力显然不及第一种,也就是第一种更优,所以力量大的在下面一定比力量轻的在下面更好。所以我们按力量排序。

因此按照力量升序开始检索,只要满足力量大于本身重力+f[i],就可以更新max及f[i+1],这里更新从大到小是因为我们更新的是f[i+1],如果从小到大,就破坏的后面的更新。

这里还要提一句,就是力量小于本身体重的,连自己都拖不动,是不会被处理的:

#include<stdio.h>

#include<string.h>

#include<stdlib.h>

#define INF 100000000

#define MAXN 6000



int n, w[MAXN], s[MAXN], f[MAXN], r[MAXN];

int cmp(const void *_p, const void *_q)

{

    int *p = (int *)_p;

    int *q = (int *)_q;

    return s[*p] - s[*q];    

}



void solve()

{

    memset(f, 0x3f, sizeof(f));

    f[0] = 0;

    for(int i = 1; i < n; i ++) r[i] = i;

    qsort(r+1, n, sizeof(r[0]), cmp);

    int max = 0;

    for(int i = 1; i < n; i ++)

        for(int j = max; j >= 0; j--)

            if(f[j] + w[r[i]] < s[r[i]] && f[j] + w[r[i]] < f[j+1])

            {

                f[j+1] = f[j] + w[r[i]];

                if(j+1 > max) max = j+1;

            }

    printf("%d\n",max);

}



void init()

{

    n = 1;

    while(~scanf("%d%d",&w[n],&s[n]))

        if(w[n] <= s[n]) n ++;

    solve();

}

int main()

{

    init();

    //system("pause");

    return 0;

}

你可能感兴趣的:(uva)