Cow Acrobats [POJ-3045]
Description
Farmer John’s N (1 <= N <= 50,000) cows (numbered 1…N) are planning to run away and join the circus. Their hoofed feet prevent them from tightrope walking and swinging from the trapeze (and their last attempt at firing a cow out of a cannon met with a dismal failure). Thus, they have decided to practice performing acrobatic stunts.
The cows aren’t terribly creative and have only come up with one acrobatic stunt: standing on top of each other to form a vertical stack of some height. The cows are trying to figure out the order in which they should arrange themselves ithin this stack.
Each of the N cows has an associated weight (1 <= W_i <= 10,000) and strength (1 <= S_i <= 1,000,000,000). The risk of a cow collapsing is equal to the combined weight of all cows on top of her (not including her own weight, of course) minus her strength (so that a stronger cow has a lower risk). Your task is to determine an ordering of the cows that minimizes the greatest risk of collapse for any of the cows.
Input
-
Line 1: A single line with the integer N.
-
Lines 2…N+1: Line i+1 describes cow i with two space-separated integers, W_i and S_i.
Output
- Line 1: A single integer, giving the largest risk of all the cows in any optimal ordering that minimizes the risk.
Sample Input | Sample Output |
---|---|
3 10 3 2 5 3 3 | 2 |
题意:有n头牛牛一只踩在一只背上叠高高,每头牛有自己的重量和力量值,但他们这样做会有一个风险值,一头牛的风险值等于自身的重量加上踩在它身上的牛的总体重减去自身的力量值,
若编号为1的牛是最底下的牛,编号为n的牛是最上面的牛,则编号为i的牛的风险值s
s = ∑ k = i n a [ k ] . w − a [ i ] . s s=\sum_{k=i}^na[k].w - a[i].s s=k=i∑na[k].w−a[i].s
现求风险值最大的牛能达到的最小风险值是多少(最小化最大值
思路:
已知一头牛的风险值
r
i
s
=
∑
k
=
i
+
1
n
a
[
k
]
.
w
−
(
a
[
i
]
.
w
+
a
[
i
]
.
s
)
ris=\sum_{k=i+1}^na[k].w - (a[i].w+ a[i].s)
ris=∑k=i+1na[k].w−(a[i].w+a[i].s)
且第i头牛的风险值不会受到在它上面的牛的顺序影响
假设现在有
牛
1
牛_1
牛1和
牛
2
牛_2
牛2,体重和力量值分别对应
w
1
w_1
w1,
s
2
s_2
s2和
w
2
w_2
w2,
s
2
s_2
s2,牛1和牛2挨着站,它们上面的牛的体重总和为
s
u
m
sum
sum。
情况a:若牛1在牛2背上
则
牛1风险值为:
r
i
s
a
1
=
s
u
m
−
s
1
risa_1=sum-s_1
risa1=sum−s1
牛2风险值为:
r
i
s
a
2
=
s
u
m
+
w
1
−
s
2
risa_2=sum+w1-s2
risa2=sum+w1−s2
情况b:若牛2在牛1背上
则
牛1风险值为:
r
i
s
b
1
=
s
u
m
+
w
2
−
s
1
risb_1=sum+w2-s1
risb1=sum+w2−s1
牛2风险值为:
r
i
s
b
2
=
s
u
m
−
s
2
risb_2=sum-s2
risb2=sum−s2
现在要使得牛1在牛2背上的情况更优,即情况a中最大的风险值小于情况b中最大的风险值
r
i
s
a
2
<
r
i
s
b
1
risa_2<risb_1
risa2<risb1
有
s
u
m
+
w
1
−
s
2
<
s
u
m
+
w
2
−
s
1
sum+w_1-s_2<sum+w_2-s_1
sum+w1−s2<sum+w2−s1
即
w
1
+
s
1
<
w
2
+
s
2
w_1+s_1<w_2+s_2
w1+s1<w2+s2
这样我们可以根据
w
+
s
w+s
w+s的大小进行排序,最小的站在牛堆的最顶端,从上到下计算风险值,不断更新最大值。此时得到的最大值一定是所有情况中最小的。
#include<iostream>
#include<algorithm>
using namespace std ;
#define ll long long
const ll N = 1e6+9 ;
void updata( ll &a , ll b ){if(b>a)a=b;}
struct node{
ll w , s ;
}c[ N ];
bool cmp( node a , node b ){
return (a.s+a.w)>(b.s+b.w) ;//从大到小排序
}
ll n , s , w ;
int main(){
//while( cin >> n ){
ios::sync_with_stdio(false);
cin >> n ;
ll sum = 0 , ans = -1e18 ;
for( int i = 1 ; i <= n ; i ++ ){ cin >> c[ i ].w >> c[ i ].s ; sum += c[ i ].w ; }
sort( c+1 , c+1+n , cmp ) ;
for( int i = 1 ; i <= n ; i ++ ){
//从最底下的牛开始算风险值
ll tmp = sum-c[i].w-c[i].s ;
updata( ans , tmp ) ;
sum -= c[ i ].w ;
}
cout << ans << "\n" ;
// }
return 0 ;
}