POJ 3045 數學證明貪心解決 OR 二分
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
3 10 3 2 5 3 3
Sample Output
2
Hint
OUTPUT DETAILS: Put the cow with weight 10 on the bottom. She will carry the other two cows, so the risk of her collapsing is 2+3-3=2. The other cows have lower risk of collapsing.
題意: 一群牛在疊羅漢; 每頭牛都有一個重量W和力量值X; 在疊的時候每頭牛都有一個風險值R; 要你求總的風險值中最大的那個風險值R’
思路:想了很長時間,根本無從下手,然後就對各位大佬的思路下手了,在這裡有兩種方法來解決這個疊羅漢問題,第一種比較好寫一些;
在這裡需運用貪心的方法來解決,我們可以將每一隻牛的W+H加起來,然後從小到大的順序sort一下,然後按照將求和得到的值大的放到下面,再繼續列舉每一隻牛的危險值(可能為負數,因此要注意開始設定一個無窮小量),最終找到裡面最大的值,就是答案了;
為什麼上面的思路求解的是對的,那就需要數學證明一下:
假設當前的A,B兩隻牛的的順序就是所需的最優的順序,並且說明A在B的上面,定義一個sum代表A上面的牛的總重量,那麼:
DangerA=sum-A.s;DangerB=sum+A.w-B.s;
其中兩者的危險值都是最優的,然後將A,B兩隻牛的順序變一下,那麼此時的sum的值是不變的,因此:
DangerA'=sum+B.w-A.s;DangerB'=sum-B.s;
由於假設A在上的情況是最優的,那麼此時交換後B位置的危險值為DangerA',那麼DangeA’>=DangerB';
即sum+B.w-A.s>=sum+A.w-B.s ==> B.s+B.w>=A.s+A.w;那麼最優的放置方案應該是兩者之和大的放在下面,有次思路便能夠AC;
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include<set>
using namespace std;
typedef long long ll;
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define lep(i,l,r) for(int i=l;i>=r;i--)
const ll INF=(ll)1<<63;
const int N=1e6+400;
int n;
struct node
{
ll s,w,sum;
bool operator < (const node &a) const{
return sum<a.sum;
}
}a[50009];
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
scanf("%d",&n);
rep(i,1,n)
scanf("%lld%lld",&a[i].w,&a[i].s),a[i].sum=a[i].s+a[i].w;
sort(a+1,a+n+1);
ll ans=-INF;
ll tot=0;
rep(i,1,n){//當n為1的時候,輸出的結果是-a[1].s;
tot-=a[i].s;
ans=max(ans,tot);
tot=tot+a[i].w+a[i].s;
}
printf("%lld\n",ans);
return 0;
}