题目链接:http://poj.org/problem?id=3045
有n头奶牛叠罗汉,其中第i头奶牛的重量为wi,力量为si,每头奶牛有一个难受值di,等于他上面所有奶牛的重量和减去他的力量,现在找出一种方案,使得这n头奶牛中最大的难受值尽量小
这里有一个猜想,把wi+si作为关键字排序,大的排在后面,反正我是没有想出来,在这里简单证明一下
设i,j是相邻的奶牛,而且wi+si>wj+sj,求证:i放在下面比j放在下面更优:
则排列情况为:
..... |
..... |
j |
i |
..... |
...... |
...... |
i' |
j' |
...... |
由于i,j的位置关系对其他奶牛的难受值无关,所以我们只需要单独考虑i,j的难受值,设C为i,j上面所有奶牛的重量和
那么有di = C + wj - si ① dj = C - sj ②
di' = C - si ③ dj' = C + wi - sj ④
因为wi+si>wj+sj 所以wi - sj > wj - si 所以④>①
显然①>③,④>②成立,因此这4个难受值当中dj'是最大的,而dj'表示的是j放在i下面,因此我们只需要把i,j交换,让i放在下面,就比j放在下面更优
那么这里的i,j是相邻的两头奶牛,无法说明整体的问题,怎么办呢?
我们可以把这个混乱的顺序当做冒泡排序的过程,遇到不合法的情况交换一下就行了,因此我们只需要证明相邻两头奶牛在什么情况下有最优解,而不需要证明两头奶牛不相邻时候的情况。
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define MAXN 50005
using namespace std;
struct T
{
int w,l;
}a[MAXN];
bool cmp(T x,T y)
{
return x.w+x.l<y.w+y.l;
}
int n;
int sum,ans = -123456789;
int main()
{
scanf("%d",&n);
for(int i = 1; i <= n; i++)
{
scanf("%d%d",&a[i].w,&a[i].l);
}
sort(a+1,a+n+1,cmp);
for(int i = 1; i <= n; i++)
{
ans = max(ans,sum-a[i].l);
sum += a[i].w;
}
printf("%d\n",ans);
return 0;
}