題目連結:http://www.lydsy.com/JudgeOnline/problem.php?id=1634
題意:
約翰留下他的N只奶牛上山採木。可是,當他回來的時候,他看到了一幕慘劇:牛們正躲在他的花園裡,啃食著他心愛的美麗花朵!
為了使接下來花朵的損失最小,約翰趕緊採取行動,把牛們送回牛棚。
第i只牛所在的位置距離牛棚t[i](1 <= t[i] <= 2000000)分鐘的路程,而在約翰開始送她回牛棚之前,她每分鐘會啃食e[i](1 <= e[i] <= 100)朵鮮花。
無論多麼努力,約翰一次只能送一隻牛回棚。而運送第第i只牛事實上需要2Ti分鐘,因為來回都需要時間。
寫一個程式來決定約翰運送奶牛的順序,使最終被吞食的花朵數量最小。
題解:
貪心。
對於順序相鄰的兩隻牛a和b,交換a和b的順序,對於a和b之外的牛是沒有影響的。
將其他的牛看作一隻牛c。
當a排在b之前時,答案為:
ans1 = t[a]*(e[b]+e[c]) + t[b]*e[c]
當b排在a之前時,答案為:
ans2 = t[b]*(e[a]+e[c]) + t[a]*e[c]
假設a排在b前面的時候答案更優,則有:
ans1 < ans2
即:t[a]*(e[b]+e[c]) + t[b]*e[c] < t[b]*(e[a]+e[c]) + t[a]*e[c]
整理得:t[a]*e[b] < t[b]*e[a]
所以按照t[a]*e[b] < t[b]*e[a]排序就好了。
AC Code:
1 // before: t[a]*(e[b]+e[c]) + t[b]*e[c] 2 // after: t[b]*(e[a]+e[c]) + t[a]*e[c] 3 // if a is better: 4 // t[a]*(e[b]+e[c]) + t[b]*e[c] < t[b]*(e[a]+e[c]) + t[a]*e[c] 5 // t[a]*e[b] + t[a]*e[c] + t[b]*e[c] < t[b]*e[a] + t[b]*e[c] + t[a]*e[c] 6 // t[a]*e[b] < t[b]*e[a] 7 #include <iostream> 8 #include <stdio.h> 9 #include <string.h> 10 #include <algorithm> 11 #define MAX_N 100005 12 13 using namespace std; 14 15 struct Cow 16 { 17 int eat; 18 int tim; 19 Cow(int _eat,int _tim) 20 { 21 eat=_eat; 22 tim=_tim; 23 } 24 Cow(){} 25 friend bool operator < (const Cow &a,const Cow &b) 26 { 27 return a.tim*b.eat<b.tim*a.eat; 28 } 29 }; 30 31 int n; 32 long long ans=0; 33 Cow cow[MAX_N]; 34 35 void read() 36 { 37 cin>>n; 38 for(int i=0;i<n;i++) 39 { 40 cin>>cow[i].tim>>cow[i].eat; 41 cow[i].tim<<=1; 42 } 43 } 44 45 void solve() 46 { 47 sort(cow,cow+n); 48 int tot=0; 49 for(int i=0;i<n;i++) 50 { 51 tot+=cow[i].eat; 52 } 53 for(int i=0;i<n;i++) 54 { 55 tot-=cow[i].eat; 56 ans+=cow[i].tim*tot; 57 } 58 } 59 60 void print() 61 { 62 cout<<ans<<endl; 63 } 64 65 int main() 66 { 67 read(); 68 solve(); 69 print(); 70 }