首页 > 代码库 > poj 3045

poj 3045

/*    题意:        给定n,然后是n头牛,每头牛有一个重量w,力量s        要求把n头牛一个叠在一个头上,类似叠罗汉        对于一个叠罗汉的序列,每头牛的risk是它顶上的牛的重量之和减去它的s        对于序列的最大的risk就是这个序列的risk        问如何确定一种序列使得risk最小    解析:        首先要想到,对于相邻的两头牛,交换它们的位置,仅仅会影响他们两个的risk值        然后,对于最优系列的相邻的两头牛        w1 s1        w2 s2        最顶上的那头的顶上的牛的质量和为sum        那么第一头牛的risk就是 sum - s1   r1        第二头的为sum + w1 - s2           r2        假如交换位置之后:            sum - s2                      r3            sum + w2 - s1                 r4        有:max(r1,r2) < max(r3,r4)——r1..r4分别对应四个risk        那么,有四种假设:            r1 < r3            r1 < r4            r2 < r3            r2 < r4        当然这四个假设,每一个都还隐含了两个不等式,在这里先不写出来        因为明显有 r1 < r4 r2 > r3        所以,只剩下:            1.r1 < r3 —— r1 > r2 && r3 > r4            2.r2 < r4 —— r2 > r1 && r4 > r3        对于1:            s2 - s1 > w1 && s1 - s2 > w2,因为w1,w2都大于0,所以不符合。        所以只剩下2            得到:w1 + s1 < w2 + s2        综上,得出w+s最大的必定在最底下,按照w+s排序得到的就是最优序列。        顺便,要注意一下,risk是可以为负数的,所以初始化的时候不可以为0。*/#include <iostream>#include <cstdio>#include <algorithm>#define range(i,a,b) for (int i=a;i<=b;i++)const int maxn = 50000;typedef long long ll;using namespace std;struct Data{    ll w,s;    friend bool operator < (const Data &a,const Data &b)    {        return a.w+a.s < b.w + b.s;    }};ll n;Data dat[maxn+1];void input(ll &a){    scanf("%I64d",&a);}int main(){    input(n);    range(c,1,n)    {        input(dat[c].w);        input(dat[c].s);    }    sort(dat+1,dat+1+n);    ll sum(0);    ll risk=-(1<<29);    //初始化状态为0的话,就会WA!    range(i,1,n)    {        risk = sum - dat[i].s > risk ? sum - dat[i].s : risk;        sum += dat[i].w;    }    cout<<risk<<endl;    return 0;}

 

poj 3045