1. 程式人生 > >洛谷 P2878 [USACO07JAN]保護花朵Protecting the Flowers 題解

洛谷 P2878 [USACO07JAN]保護花朵Protecting the Flowers 題解

alt 留下 原創 bool ring bsp gist max using

此文為博主原創題解,轉載時請通知博主,並把原文鏈接放在正文醒目位置。

題目鏈接:https://www.luogu.org/problem/show?pid=2878

(本來想放bzoj的鏈接 然而bzoj這道題掛了)

【題目描述】

約翰留下他的N(N<=100000)只奶牛上山采木.他離開的時候,她們像往常一樣悠閑地在草場裏吃草.可是,當他回來的時候,他看到了一幕慘劇:牛們正躲在他的花園裏,啃食著他心愛的美麗花朵!為了使接下來花朵的損失最小,約翰趕緊采取行動,把牛們送回牛棚. 牛們從1到N編號.第i只牛所在的位置距離牛棚Ti(1≤Ti≤2000000)分鐘的路程,而在約翰開始送她回牛棚之前,她每分鐘會啃食Di(1≤Di≤100)朵鮮花.無論多麽努力,約翰一次只能送一只牛回棚.而運送第第i只牛事實上需要2Ti分鐘,因為來回都需要時間. 寫一個程序來決定約翰運送奶牛的順序,使最終被吞食的花朵數量最小.

【輸入格式】

1行輸入N,之後N行每行輸入兩個整數TiDi

【輸出格式】

一個整數,表示最小數量的花朵被吞食

【樣例輸入】

6

3 1

2 5

2 3

3 2

4 1

1 6

【樣例輸出】

86

【樣例解釋】

約翰用623415的順序來運送他的奶牛

這題做的時候是hzwer神犇出的模考題,然後錯得一塌糊塗qwq

分析:

這題用貪心來做。

單獨看牛群中的兩頭牛a、b,每頭牛擁有兩個參數D和T。

假設這兩頭牛是相鄰的,a在b之後被帶走,考慮將這兩頭牛交換順序,不會影響牛群中其他牛吃花的時間。

交換順序前 吃花數量:2*T[b]*D[a]

交換順序後 吃花數量:2*T[a]*D[b]

要使這次交換順序是有效的,也就是說交換後的吃花數量減少了

則應滿足 T[b]*D[a] > T[a]*D[b]

化簡可得 D[a]/T[a] > D[b]/T[b]

推理可知,當一頭牛的【吃花數量/帶走時間】越大時,它應該先被帶走。

簡單理解的話也可以認為是先把腿長而且能吃的奶牛帶走吧...(逃)

AC代碼:

技術分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5
#include<queue> 6 7 using namespace std; 8 const int MAXN = 100005; 9 10 struct cow 11 { 12 int t,d; 13 double jud; 14 }a[MAXN];//存儲奶牛的相關參數 15 16 long long sum[MAXN]; 17 18 bool cmp(cow a,cow b) 19 { 20 return a.jud > b.jud?1:0; 21 }//根據比值來比較結構體大小 22 23 int main() 24 { 25 int n; 26 scanf("%d",&n); 27 for(int i = 0;i < n;++ i) 28 { 29 scanf("%d%d",&a[i].t,&a[i].d); 30 a[i].jud = (double) a[i].d/a[i].t; 31 } 32 sort(a,a+n,cmp); 33 34 sum[n-1] = (long long)a[n-1].d; 35 for(int i = n-1;i >= 0;i --) 36 sum[i] = (long long)a[i].d + sum[i+1]; 37 //計算剩余的i頭奶牛每分鐘吃掉的花朵 38 long long ans = 0; 39 for(int i = 0;i < n;i ++) 40 { 41 ans += (long long)2 * a[i].t * sum[i+1]; 42 } 43 printf("%lld",ans); 44 return 0; 45 }
保護花朵 代碼

大佬說最好用乘法,直觀快速而且不用考慮精度。

……窩就是喜歡用除法嘛……窩就是覺得這樣方便……

QAQ於是下面附上乘法的代碼,@WZY大佬

技術分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <vector>
 7 #include <queue>
 8 inline void read(long long &x)
 9 {
10     x = 0;char ch = getchar();char c = ch;
11     while(ch > 9 || ch < 0)c = ch, ch = getchar();
12     while(ch <= 9 && ch >= 0)x = x * 10 + ch - 0,ch = getchar();
13     if(c == -)x = -x; 
14 }
15 const long long MAXN = 1000000 + 10;
16 const int INF = 0x3f3f3f3f;
17 
18 long long n,T[MAXN],D[MAXN],cnt[MAXN];
19 
20 bool cmp(long long a, long long b)
21 {
22     return D[a] * T[b] > D[b] * T[a];
23 }//直接根據乘法結果排序 
24 
25 long long ans;
26 long long sum;
27 
28 int main()
29 {
30 //    freopen("data.txt", "r", stdin);
31     read(n);
32     for(register long long i = 1;i <= n;++ i)
33     {
34         read(T[i]);read(D[i]);
35         cnt[i] = i;
36         sum += D[i];
37     }
38     std::sort(cnt + 1, cnt + 1 + n, cmp);
39     for(register long long i = 1;i <= n;++ i)
40     {
41         sum -= D[cnt[i]];
42         ans += ((long long)(sum * T[cnt[i]]) << 1);
43     }
44     printf("%lld", ans);
45     return 0;
46 }
保護花朵 by嘒彼小星

或許這就是大佬吧

洛谷 P2878 [USACO07JAN]保護花朵Protecting the Flowers 題解