洛谷P1080--国王游戏(数学+贪心+大数: python / java)

题意:
在这里插入图片描述
思路:任取队列中的两个相邻位置来推,假设位置为 i 和 i+1,设位置前面已经积累的左手金币数量为X,对于位置i,ans1=max(X/bi, Xai/ b(i+1))(设max内为y1,y2),交换两位置:ans2=max(X / b(i+1),Xa(i+1)/bi)(设max内为y3,y4),显然,y3<=y2,y1<=y4; 要使ans1<ans2(即前面一种排法比后面优),则有:y2>y4,即Xai/b(i+1)>Xa(i+1)/bi;
化简有:ai*bi<a(i+1)*b(i+1); 同理,要是后面一种方式更优做法类似;
这样可以看出,要使排序取得最优方案,即给出的奖赏最小,则要按 ai * bi 从小到大排,同时由于数据范围远超过了longlong 范围,故要用java/python写大数(当然也可以C++高精度)

代码如下(含python版及java版):
1.python版:

n=int(input())
a,b=input().split()
a=int(a)
b=int(b)
per=[]
for i in range (1,n+1):
    l,r=input().split()
    per.append((int(l),int(r)))
per.sort(key=lambda x:x[0]*x[1])
ans=-1
nowleft=a
for i in range (0,n):
    ans=max(ans,nowleft//(per[i])[1])
    nowleft*=(per[i])[0]
print(ans)

2.java版:

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

public class Main{
    private static class person{
        BigInteger l;
        BigInteger r;
    }
    final static int maxn=10005;
    static person[] per;

    private static class cmp implements Comparator<person>{
        @Override
        public int compare(person a,person b)
        {
            if((a.l).multiply(a.r).compareTo((b.l).multiply(b.r))<0)
            {
                return -1;
            }
            else if((a.l).multiply(a.r).compareTo((b.l).multiply(b.r))==0)
            {
                return 0;
            }
            else
            {
                return 1;
            }
        }
    }

    public static void main(String []args){
        Scanner cin=new Scanner(System.in);
        int n=cin.nextInt();
        per=new person[maxn];
        per[0]=new person();
        per[0].l=cin.nextBigInteger();
        per[0].r=cin.nextBigInteger();
        for(int i=1;i<=n;i++)
        {
            per[i]=new person();
            per[i].l=cin.nextBigInteger();
            per[i].r=cin.nextBigInteger();
        }
        Arrays.sort(per,1,n+1,new cmp());

        BigInteger nowleft=per[0].l;
        BigInteger ans=BigInteger.valueOf(0);
        for(int i=1;i<=n;i++)
        {
            ans=ans.max(nowleft.divide(per[i].r));
            nowleft=nowleft.multiply(per[i].l);
        }
        System.out.println(ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值