此题仅需用 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<stdio.h>
#include<stdlib.h>
#include<string.h>
#define inf 0x7fffffff
#define Maxn 100010
struct floor
{
int w,s;
}f[Maxn];
int n;
int cmp(const void *a,const void *b){
struct floor *c=(struct floor *)a;
struct floor *d=(struct floor *)b;
return (c->s+c->w)-(d->s+d->w); //sum+wi-si+1<sum+wi+1-si
}
int main() //典型的贪心算法
{
int i,j,k,flag;
long long sum,min,max;
while(scanf("%d",&n)!=EOF){
sum=0;
for(i=1;i<=n;i++){
scanf("%d %d",&f[i].w,&f[i].s);
sum+=f[i].w;
}
qsort(f+1,n,sizeof(f[1]),cmp);
min=sum-f[n].w-f[n].s; //最下面那层即为pdv最大值
printf("%I64d\n",min);
}
//system("pause");
return 0;
}