P1080国王游戏
贪心
国王游戏
怎么对大臣排序???
绝对按照右手排,貌似不对,md
假设 \(n==2\) 时候的到一种 \(cmp\) 的函数,然后直接排序就可以了,这就是贪心,信息学是一门不需要证明的许可,不用证明,对于\(\%90\) 的贪心题都可这么做,\(nb\)
思路
我们不妨设 \(n=2\) 时,最大获益金币的人最小
那第一个人 \(A\) 为 \(a.r,a.l\), 第二个人 \(B\) 为 \(b.r,b.l\)
设皇上的左右手分别为 \(z[0].l, z[0].r\)
当 \(A\) 在 \(B\) 的前边时
\(A\) 的钱
\(B\) 的钱
答案 \(v1\) 为 \(max\{\frac{z[0].l}{a.r},\frac{z[0].l\times a.l}{b.r}\}\)
当 \(B\) 在 \(A\) 前面时
同理可得答案 \(v2\) 为 \(max\{\frac{z[0].l}{b.r},\frac{z[0].l\times b.l}{a.r}\}\)
最终答案就是 \(max\{v1,v2\}\)
那么当 \(n!=2\) 时呢,假设现在就这两个人需要我们讨论,我们不是需要国王到自己前面人左手的数嘛,我们设这个数为 \(x\) 那么式子的就是变成
答案就是 \(ans=max\{v1,v2\}\)
当我们把分母去掉即,\(v1,v2\) 都乘以\(a.r\times b.r\)
化简得
我们发现 \(x\) 可以消掉,即在这里答案的大小不受 \(x\) 的影响,那么我们的式子就可以变成
有了式子我们就可以利用冒泡排序,时间复杂度为 \(O(n^2)\)
//冒泡排序
#include <iostream>
using namespace std;
struct node{
int l,r;
};
node z[100010];
int cmo(node a, node b)//a是否放在b的前面
{
int v1 = max(z[0].l/a.r, z[0].l*a.l / b.r);
int v2 = max(z[0].l/b.r, z[0].l*b.l / a.r);
if(v1<v2) return 1;
else return 0;
}
int main()
{
for (int i=1;i<=n;i++)
for (int j=1;j<n;j++)
{
if(cmp(z[j+1],z[j])) swap(z[j+1], z[j]);
}
}// O(n^2)
其实就变成了比较这四个数的大小,这样就可以进行贪心了
贪心式子是否可以优化呢?
我们不难发现 \(b.r<b.l\times b.r\) 和 \(a.r<a.l\times a.r\)
那么我们比较这是两个还有意义嘛,他们两个本质上就比右侧的大,所以剔除就好了,因此式子就化简成
贪心化简的本质
- 去分母
- 去除公共项
- 出去无用项,即不可能更好
- 简化完毕!
struct node{
int l, r;
};
node z[B];
int ans=1, n;
int cmp(node a, node b)
{
return a.l*a.r<b.l*b.r;
}
int main() {
scanf("%d",&n);
scanf("%d%d",&z[0].l,&z[0].r);
for (int i=1;i<=n;i++)
scanf("%d%d",&z[i].l,&z[i].r);
sort(z+1,z+1+n,cmp);
for (int i=0;i<n;i++) ans*=z[i].l;
printf("%d",ans/z[n].r);
return 0;
}