一二三四五 上山打老虎

NC16561-国王的游戏

题目链接:https://ac.nowcoder.com/acm/problem/16561
参考题解链接:https://ac.nowcoder.com/acm/contest/view-submission?submissionId=46518796

题意:1个国王给n个大臣分奖赏,国王和大臣左右手中分别有值,相当于给定(1+n)个l和r值,第一个为国王,每个大臣所得的奖赏为 这个大臣前的所有人左手值的乘积÷本大臣右手值,要求排序使得奖赏最多的大臣所得金币最少,输出奖赏最多大臣的奖赏数值。

思路:贪心,本题相当于对所有大臣进行排序,使得上述最大奖赏值最小,进行局部最优解分析:
如果存在两个大臣 大臣a左右手值为al和ar,大臣b 左右手值为bl,br,两大臣前左手乘积为L:
当大臣a在b前边的时候
①大臣a所得奖赏:\(\frac{L}{ar}\)
②大臣b所得奖赏:\(\frac{L\times al}{br}\)
当大臣b在a前边的时候:
③大臣a所得奖赏:\(\frac{L\times bl}{ar}\)
④大臣b所得奖赏:\(\frac{L}{br}\)
由于al,ar,
明显:\(①\leq ③\)\(②\geq ④\) ,假设ab顺序为正解,则只需要满足\(③\leq②\)即可实现ab顺序中的奖赏最多的大臣所获得的奖赏值小于等于ba顺序中奖赏最多的大臣所获奖赏值。
将除法公式传换成乘法来避免精度和除0等可能存在问题,得到排序的依据为:\(al\times ar \geq bl\times br\) 通过这个顺序进行排序即可达到局部贪心实现最优解
坑点:本题数据范围导致40%的测试数据中 左手中的值乘积会爆long long 所以需要加一个大数乘int,大数除int 以及大数之间大小比较的处理,具体实现有参考上述题解链接所指题解。

反思:要认真分析数据范围,可能会出现爆int或者long long情况哎

#include<cstdio>
#include<algorithm>

using namespace std;
struct node{
    int l,r;
}a[(int)1e4+5];
bool cmp(struct node s,struct node t){
    return 1LL*s.l*s.r<1LL*t.l*t.r;
}
struct num{
    int number[10005]={0};//在0位置存储数值长度
}ans,res;
void mul(int x){
    int len=ans.number[0];
    for(int i=1;i<=len;i++){
        ans.number[i]*=x;
    }
    for(int i=1;i<=len;i++){
        ans.number[i+1]+=ans.number[i]/10;
        ans.number[i]%=10;
    }
    while(ans.number[len+1]>0){
        len++;
        ans.number[len+1]=ans.number[len]/10;
        ans.number[len]%=10;
    }
    ans.number[0]=len;
}

struct num div(struct num & temans,int x){
    int num=0;
    struct num temres;
    int len=temans.number[0];
    for(int i=len;i>=1;i--){
        num=num*10+temans.number[i];
        temres.number[i]=num/x;
        num%=x;
    }
    while(temres.number[len]==0)len--;
    temres.number[0]=len;
    return temres;
}
bool comparen(const struct num l,const struct num r){//>
    if(l.number[0]>r.number[0])return true;
    for(int i=l.number[0];i>=1;i--){
        if(l.number[i]>r.number[i])return true;
        else if (l.number[i]<r.number[i])return false;
    }
    return false;
}
int main (){
    int n;
    scanf("%d",&n);
    for(int i=0;i<=n;i++){
        scanf("%d%d",&a[i].l,&a[i].r);
    }
    sort(a+1,a+n+1,cmp);
    int s=a[0].l,len=1;
    while(s){
       ans.number[len++]=s%10;
        s/=10;
    }
    ans.number[0]=len-1;
    for(int i=1;i<=n;i++){
        struct num tem=div(ans,a[i].r);
        if(comparen(tem,res))res=tem;
         mul(a[i].l);
    }
    for(int i=res.number[0];i>=1;i--)
        printf("%d",res.number[i]);
    return 0;
}

没进行高精度处理,只能过60%的代码

#include<cstdio>
#include<algorithm>

using namespace std;
struct node{
    int l,r;
}a[(int)1e4+5];
bool cmp(struct node s,struct node t){
    return 1LL*s.l*s.r<1LL*t.l*t.r;
}
int main (){
    int n;
    scanf("%d",&n);
    for(int i=0;i<=n;i++){
        scanf("%d%d",&a[i].l,&a[i].r);
    }
    sort(a+1,a+n+1,cmp);
   long long  ans=a[0].l;
   long long res=0;
    for(int i=1;i<=n;i++){
        res=max(res,ans/a[i].r);
        ans=1LL*ans*a[i].l;
    }
    printf("%lld",res);
    return 0;
}

posted @ 2021-01-23 19:03  黒川川  阅读(103)  评论(0)    收藏  举报