hdu 4296 Buildings

http://acm.hdu.edu.cn/showproblem.php?pid=4296

此题仅需用 w+s 的值进行从小到大的排序即可  注意  结果可能超32位

证明  只需要证明相邻的即可 因为它们不会影响前面的PDV 也不会影响后面的PDV

假设 w1+s1  <   w2+s2  在此之前的的w和为 X

那么 w1+s1 在前则 最大PDV 为 P1=max(X-s1,X+w1-s2);

如果 w2+s2 在前则 最大PDV 为 P2=max(X-s2,X+w2-s1);

我们可以同时把X去掉 则

P1=max( -s1,w1-s2);

P2=max( -s2,w2-s1);

再将所有值加上 s1+s2 则

P1=max(s2,w1+s1);

P2=max(s1,w2+s2);

那么P2 和 P1 那个小呢

因为有 w2+s2>w1+s2  且 w2+s2>=s2

所有P2>P1

所以我们要P1的值 也就是将和小的排在前面 如果相等 会发现顺序无关

代码:

#include <iostream>

#include <cstdio>

#include <cstring>

#include <queue>

#include <algorithm>



#define LL long long



//#pragma comment(linker, "/STACK:1024000000,1024000000")

using namespace std;



const int INF=0x5fffffff;

const int N=100005;

struct node

{

    int w,s;

}mem[N];

bool cmp(node x,node y)

{

    return (x.w+x.s)<(y.w+y.s);

}

int main()

{

    //freopen("data.txt","r",stdin);

    int n;

    while(scanf("%d",&n)!=EOF)

    {

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

        {

            scanf("%d %d",&mem[i].w,&mem[i].s);

        }

        sort(mem+1,mem+1+n,cmp);

        mem[0].s=mem[0].w=0;

        LL ans=0;

        LL temp=0;

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

        {

            temp=temp+mem[i-1].w+mem[i-1].s-mem[i].s;

            if(temp>ans)

            ans=temp;

        }

        cout<<ans<<endl;

    }

    return 0;

}



 

 

你可能感兴趣的:(Build)