堆积木

现在有N块积木,每块积木都有自重W和正常状态下的承重能力F,现在要把这N块积木垒在一起,但是有可能某块积木的负重超过了它在正常状态下的承重能力,那么这块积木就有被压坏的危险,请问应该如何堆这N块积木使得N块积木中最大的压力指数最小。这里定义压力指数为该积木的负重与其在正常状态下的承重能力的差值。

1≤N≤50000,1≤W≤10000,1≤F≤10^9。

 输入:第一行为一个正整数N,表示有N块积木,第2行到第N+1行,分别两个整数,表示第i块积木的w[i]和f[i]的值。

输出:共一行,表示最大压力指数的最小值。

输入样例:

3

10 3

2 5

3 3

输出样例:

2

sol:贪心(交换法),贪心策略是将每个积木的自重w[i]+承重f[i],按从小到大的顺序排列,然后依次模拟从上到小取积木块,每堆一块积木,就算出一个压力指数,然后从取所有积木压力指数的最小值。如果有其它更优的方案,那么只能是通过交换积木块实现。如:

A在B上面:                           B在A上面

A  压力值为0-f[A]                   B  压力值为0-f[B]

B  压力值为w[A]-f[B]              A  压力值为w[B]-f[A]

 

从上面的式子可知:这两种方法4块积木分别的压力值有如下关系:w[B]-f[A]>0-f[A],w[A]-f[B]>0-f[B],到底A放B上面更优还是B放A上面更优,那我们就要比较w[A]-f[B]与w[B]-f[A]的值,假设前者小于后者,即w[A]-f[B]<w[B]-f[A],变形得w[A]+f[A]<w[B]+f[B],即我们将自重与承重和小的放在上面更优。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 const int maxn=50010;
 5 using namespace std;
 6 
 7 inline int read()
 8 {
 9     char ch; int tmp=0;
10     while(ch=getchar()) if('0'<=ch && ch<='9') break;
11     for(;'0'<=ch && ch<='9';ch=getchar()) tmp=tmp*10+ch-'0';
12     return tmp;
13 }
14 
15 struct zy
16 {
17  int w,p;
18 }a[maxn];
19 
20 inline bool cmp(zy a,zy b)
21 {
22  return a.w+a.p<b.w+b.p;
23 }
24 int n;
25 void init()
26 {
27  n=read();
28  for (int i=1;i<=n;++i)
29   {
30    a[i].w=read();
31    a[i].p=read();
32   }
33  sort(a+1,a+n+1,cmp);
34 }
35 
36 void put_ans()
37 {
38  int ans=-2147483646;
39  int tot=0;
40  for (int i=1;i<=n;++i)
41   {
42    ans=max(ans,tot-a[i].p);
43    tot+=a[i].w;
44   }
45  printf("%d",ans);
46 }   
47 
48 int main()
49 {
50  init();
51  put_ans();
52  return 0;
53 }
posted @ 2020-01-03 15:48  蘑菇JJ  阅读(322)  评论(0编辑  收藏  举报