hdu4296 Buildings(贪心)

来源:互联网 发布:通达信vol源码 编辑:程序博客网 时间:2024/05/18 01:09

除夕夜刷题,好没效率。。。

还是没搞懂为何排序函数是按a.w + a.s < b.w + b.s。。。

不过尽力了,总比不看强吧。。。

-----------------------------------分割线-----------------------------------------------------

第二天想通了。。。

所谓的PDV,就是潜在损坏值(Potential Damage Value),每块板的PDV = 该板上面所有板(不包括本板)的重量 - 本板的强度。PDV越大,越容易损坏,是不是物理上很容易想通呀~。则一堆板的PDV = 该堆板中最大的PDV,直观理解就是干掉了这块板就破坏了整个堆的木板。

假设只有两块板,a和b,很显然下面的比上面的容易损坏,所以下面的PDV大。假设a在上面,其PDV值 = pdvb = wa - sb。假设b在上面,其PDV值 = pdva = wb - sa。然后两个值取最小,若a在上面的PDV小,则 wa - sb < wb - sa,即wa + sa < wb + sb。同理,若b在上面的PDV小,则wb + sb < wa + sa。上述并不是想得出递推公式,而是想说明w和s之间的关系是加减的关系。脑洞再进一步大一点,我们应该把越重强度越大的木板放在最下面,如此推出应该按照重量强度和从小到大排序然后处理的方案。

网上看了好多方法,个人认为他们的公式推理不严谨,但我也退不出严谨的公式,所以只能这样想了。

贪心任重而道远啊。。。

#include <stdio.h>#include <string.h>#include <cstdio>#include<cstring>#include <algorithm>using namespace std;const int N = 100005;const int INF = 1<<27;struct FLOOR{    int w;    int s;}flo[N];bool cmp(const FLOOR &a,const FLOOR &b){    return a.w + a.s < b.w + b.s;}int main(){  //  freopen("in.txt", "r", stdin);    int n, i;    __int64 maxx, sum;    while(~scanf("%d", &n))    {        sum = 0;        for(i = 0; i < n; i ++)            scanf("%d%d", &flo[i].w, &flo[i].s);        sort(flo, flo + n, cmp);        maxx = sum = 0;        for(i = 0; i < n; i ++)        {            maxx = max(maxx, sum - flo[i].s);            sum += flo[i].w;        }        printf("%I64d\n", maxx);    }    return 0;}


0 0