贪心(根据数学表达式确定贪心方法)
奎奎发红包
题目
奎奎给
n
个人发红包,每个人都两个值v[i]
和t[i]
,t[i]
代表给第i
个人发红包所需的时间。
每个人的红包大小为v[i]*t
,t
表示这个人的等待时间(包括自己所需时间)。
问最少花多少钱能满足每一个人?输入
4 1 4 2 3 3 2 4 1
输出
35
考虑相邻的两个人a,b
,如果a
排在前面,代价为
a
.
v
∗
a
.
t
+
b
.
v
∗
(
a
.
t
+
b
.
t
)
a.v*a.t+b.v*(a.t+b.t)
a.v∗a.t+b.v∗(a.t+b.t);如果b
排在前面,代价为
b
.
v
∗
b
.
t
+
a
.
v
∗
(
a
.
t
+
b
.
t
)
b.v*b.t+a.v*(a.t+b.t)
b.v∗b.t+a.v∗(a.t+b.t)。对两式进行化简得:如果
a
.
t
∗
b
.
v
<
a
.
v
∗
b
.
t
a.t*b.v<a.v*b.t
a.t∗b.v<a.v∗b.t,则a
应该排在前面,也就是
a
.
t
a
.
v
<
b
.
t
b
.
v
\frac{a.t}{a.v}<\frac{b.t}{b.v}
a.va.t<b.vb.t
所以按照
t
v
\frac{t}{v}
vt的排序,但需要特别考虑0的情况,因为v=0
时不用花钱,所以可以放到最后不管。
#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
#define endl '\n'
typedef long long ll;
const int maxn = 1e5 + 10;
struct node {
int v, t;
bool operator<(const node b) const
{
return 1.0 * this->t / this->v < 1.0 * b.t / b.v;
}
} a[maxn];
int n, t, v, num;
bool cmp(node a, node b)
{
return 1.0 * a.t / a.v < 1.0 * b.t / b.v;
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> v >> t;
if (v != 0) {
a[i].v = v;
a[i].t = t;
num++;
}
}
sort(a + 1, a + 1 + num);
ll ans = 0, sum = 0;
for (int i = 1; i <= num; i++) {
sum += a[i].t;
ans += a[i].v * sum;
}
cout << ans << endl;
}