【乘积排序】 国王游戏
传送门
题意
国王有两个数,每个大臣有两个数,国王始终站在队伍的最前面,每个大臣获得的奖励是他前面所有人左手上的乘积除以他右手上的数,请安排大臣的顺序,使得奖励最大的大臣获得的奖励最小
数据范围
\(1\leq n\leq 10000\)
\(1\leq a,b \leq 10000\)
题解
贪心策略:
直接将所有大臣按左右手上的数的乘积从小到大排序,得到的序列就是最优排队方案。
贪心证明:邻项交换
假设按照乘积升序排列的序列中第\(i\)和第\(i+1\)项的奖励分别为 \(\frac {\prod_{j=1}^{i-1} a_{j}}{b_{i}} ,\frac {\prod_{j=1}^{i} a_{j}}{b_{i+1}}\)
交换后的奖励分别为\(\frac {\prod_{j=1}^{i-1} a_{j}}{b_{i+1}} ,\frac {\prod_{j=1}^{i-1} a_{j}·a_{i+1}}{b_{i}}\)
去掉重复项\(\frac {\prod_{j=1}^{i-1} a_{j}}{b_{i}}\)后,
- 交换前:\(\frac{1}{b_{i}} , \frac{a_{i}}{b_{i+1}}\)
- 交换后:$\frac{1}{b_{i+1}} , \frac{a_{i+1}}{b_{i}} $
易知:
- $ \frac{a_{i+1}}{b_{i}} > \frac{1}{b_{i}}$
- \(\frac{a_{i}}{b_{i+1}} > \frac{1}{b_{i+1}}\)
所以只需要比较\(\frac{a_{i+1}}{b_[i]}\)和\(\frac{a_{i}}{b_{i+1}}\)的大小即可
\(\frac{a_{i+1}}{b_[i]} > \frac{a_{i}}{b_{i+1}}\)
可以得到
\(a_{i+1} b_{i+1} > a_{i} b_{i}\)
所以乘积小的得到的结果更小
Code
import java.util.*;
import java.math.BigInteger;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Comparator;
class ele{
int left;
int right;
public ele(int left,int right){
this.left=left;
this.right=right;
}
public int getleft(){
return this.left;
}
public int getright(){
return this.right;
}
}
public class Main{
Scanner sc=new Scanner(System.in);
int n;
ele e[];
public void input(){
n = sc.nextInt();
e = new ele[n+10];
for(int i=0;i<=n;i++){
e[i]=new ele(sc.nextInt(),sc.nextInt());
}
}
public void cal(){
Arrays.sort(e,1,n+1,new Comparator<ele>(){
public int compare(ele a,ele b){
return (a.getleft() * a.getright() - b.getleft() * b.getright());
}
});
BigInteger pre = new BigInteger(String.valueOf(e[0].getleft()));
BigInteger mx = BigInteger.ZERO;
for(int i=1;i<=n;i++){
if(pre.compareTo(new BigInteger(String.valueOf(e[i].getright()))) < 0){
if(new BigInteger("1").compareTo(mx) > 0){
mx = new BigInteger("0");
}
}
else{
BigInteger tmp = pre.divide(new BigInteger(String.valueOf(e[i].getright())));
if(tmp.compareTo(mx) > 0){
mx=tmp;
}
}
pre=pre.multiply(new BigInteger(String.valueOf(e[i].getleft())));
}
System.out.println(mx);
}
public static void main(String[] args){
Main solve = new Main();
solve.input();
solve.cal();
}
}