AcWing 114. 国王游戏(贪心、大数处理)

题干:

恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。

首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。

然后,让这 n 位大臣排成一排,国王站在队伍的最前面。

排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:

排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。

国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。

注意,国王的位置始终在队伍的最前面。

输出只有一行,包含一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。

1≤n≤1000
0<a,b<10000

思路:

用局部最优推出整体最优。因为要重新排序,所以可以看作是按照某种原则的冒泡排序,那我们只需要比较相邻两人的金币数就可以了。

懒就贴图了
在这里插入图片描述
得出我们只需要按l*r从小到大排序就行,然后考虑极限情况 10000 1000 {10000}^{1000} 100001000(其实也没那么大,但还是尽量开大点),所以需要大数的乘法和除法。
这里是重写了结构体的乘号、除号、小于号。
具体实现见代码

#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <map>
#include <iostream>
#include <algorithm>
#define ll long long
using namespace std;
struct stu
{
    int l;
    int r;
}t[1100];
struct bigint
{
    int a[110000];
    int len;
    bigint()
    {
        memset(a,0,sizeof(a));
        len=0;
    }
    bigint(int t)
    {
        memset(a,0,sizeof(a));
        len=0;
        while(t)
        {
            a[len++]=t%10;
            t/=10;
        }
    }
    bigint operator *(const int &b)const {
        bigint t;
        t.len=len;
        for(int i=0;i<len;i++){
            t.a[i]=a[i]*b;
        }
        for(int i=0;i<len;i++){
            t.a[i+1]+=t.a[i]/10;
            t.a[i]%=10;
        }
        while(t.a[t.len]>0){
            t.a[t.len+1]+=t.a[t.len]/10;
            t.a[t.len]%=10;
            t.len++;
        }
        return t;
    }
    bigint operator /(const int &b)const {
        bigint t;
        t.len=len;
        int temp=0;
        for (int i=len-1;i>=0;i--)
        {
            temp= temp*10+a[i];
            t.a[i]=temp/b;
            temp%=b;
        }
        while(!t.a[t.len-1]&&t.len>1) {
            t.len--;
        }
        return t;
    }
    bool operator <(const bigint &b)const
    {
        if(len==b.len)
        {
            int i;
            for(i=len;i>=0;i--){
                if(a[i]>b.a[i])
                    return false;
                else if(a[i]<b.a[i])
                    return true;
            }
            return false;
        }
        else
            return len<b.len;
    }
};
bool cmp(stu a,stu b)
{
    if(a.l*a.r==b.r*b.l)
        return a.l<b.l;
    return a.l*a.r<b.r*b.l;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n+1;i++){
        scanf("%d%d",&t[i].l,&t[i].r);
    }
    sort(t+1,t+n+1,cmp);
    bigint ans,now,x=1;
    for(int i=1;i<n+1;i++){
        if(t[i].l==0)
            break;
        x=x*t[i-1].l;
//        for(int i=x.len-1;i>=0;i--){
//            printf("%d",x.a[i]);
//        }
//        cout<<endl;
        if(t[i].r==0)
            break;
        now=x/t[i].r;
//        for(int i=now.len-1;i>=0;i--){
//            printf("%d",now.a[i]);
//        }
//        cout<<endl;
//        cout<<endl;
        if(ans<now)
            ans=now;
    }
    for(int i=ans.len-1;i>=0;i--){
        printf("%d",ans.a[i]);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值