洛谷 P2878 [USACO07JAN]保护花朵Protecting the Flowers 题解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P2878 [USACO07JAN]保护花朵Protecting the Flowers 题解相关的知识,希望对你有一定的参考价值。

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置。

题目链接: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 题解的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P2878 [USACO07JAN]保护花朵Protecting the Flowers 题解

P2878 [USACO07JAN]保护花朵Protecting the Flowers - 贪心

USACO 保护花朵 Protecting the Flowers, 2007 Jan

[USACO Open07] 保护花朵 --贪心

洛谷P2879 [USACO07JAN]区间统计Tallest Cow

洛谷 P2879 [USACO07JAN]区间统计Tallest Cow 题解