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; }