题意:
牛客网
有N头牛在吃花,牛i距离家有Ti分钟的路程,且每分钟能吃Di朵花,你一次只能带一头牛,请安排送牛回家的顺序,让牛吃掉的花的总数最少并输出(当你往一头牛那边走和带着牛回家的时候牛都不会吃花,虽然题目好像没说往牛那边走的时候不会吃,但是好像确实不会吃)
思路:
我们知道,在把牛送回家的队列中,改变任意两头相邻的牛的顺序并不会对他们前面或后面的牛吃的花的数量造成影响,所以为了让吃的花的总数最少,我们应该调整每相邻两头牛的位置,让他们俩吃的花最少,这样整个队列中的牛吃的花的数就最少
我们假定队列中某一位置有两头相邻的牛A、B,他们送回家的时间和每分钟吃花的数量分别为 a T a_{T} aT、 a D a_{D} aD、 b T b_{T} bT、 b D b_{D} bD ,把在A之前的所有牛送回家所需时间为 p r e T pre_{T} preT
前面的牛 | A | B |
---|---|---|
p r e T pre_{T} preT | a T a_{T} aT、 a D a_{D} aD | b T b_{T} bT、 b D b_{D} bD |
假定此时以AB为顺序把牛送回家比以BA顺序把牛送回家吃掉的花的数更少,由题意得出不等式:
(
2
×
p
r
e
T
×
a
D
+
2
×
(
p
r
e
T
+
a
T
)
×
b
D
)
≤
(
2
×
p
r
e
T
×
b
D
+
2
×
(
p
r
e
T
+
b
T
)
×
a
D
)
(2 \times pre_{T} \times a_{D} + 2 \times (pre_{T} + a_{T}) \times b_{D}) \leq (2 \times pre_{T} \times b_{D} + 2 \times (pre_{T} + b_{T}) \times a_{D})
(2×preT×aD+2×(preT+aT)×bD)≤(2×preT×bD+2×(preT+bT)×aD)
将不等式化简得到:
a
T
a
D
≤
b
T
b
D
\frac{a_{T}}{a_{D}} \leq \frac{b_{T}}{b_{D}}
aDaT≤bDbT
所以我们只需要把牛按照这个不等式进行排序,再计算吃掉的花的数量就好了
代码
*用int会爆掉
*用简单的for循环进行排序会超时
#include <iostream>
#include <algorithm>
using namespace std;
typedef struct cow {
int T; //距离barn的路程
int D; //每分钟能吃多少花
float rate; //T/D
} cow;
int main() {
int N; //牛的数量
cin >> N;
cow cows[N];
for (int i = 0; i < N; ++i) {
cin >> cows[i].T;
cin >> cows[i].D;
cows[i].rate = 1.0f * cows[i].T / cows[i].D;
}
//给牛排序
sort(cows, cows + N, [](cow a, cow b) { return a.rate < b.rate; });
unsigned long long usedTime = 0;
unsigned long long destroyedFlowers = 0;
for (cow &c:cows) {
destroyedFlowers += 2 * usedTime * c.D;
usedTime += c.T;
}
cout << destroyedFlowers;
}