国王游戏(codevs 1198)

题目描述

恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 n 位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。

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

输入输出格式

输入格式:

第一行包含一个整数 n,表示大臣的人数。

第二行包含两个整数 a和 b,之间用一个空格隔开,分别表示国王左手和右手上的整数。

接下来 n 行,每行包含两个整数 a 和 b,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。

输出格式:

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

输入输出样例

输入样例#1:

3 
1 1 
2 3 
7 4 
4 6 

输出样例#1:

2

说明

【输入输出样例说明】

按 1、2、3 号大臣这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;

按 1、3、2 这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;

按 2、1、3 这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;

按 2、3、1 这样排列队伍,获得奖赏最多的大臣所获得金币数为 9;

按 3、1、2 这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;

按 3、2、1 这样排列队伍,获得奖赏最多的大臣所获得金币数为 9。

因此,奖赏最多的大臣最少获得 2 个金币,答案输出 2。

【数据范围】

对于 20%的数据,有 1≤ n≤ 10,0 < a、b < 8;

对于 40%的数据,有 1≤ n≤20,0 < a、b < 8;

对于 60%的数据,有 1≤ n≤100;

对于 60%的数据,保证答案不超过 109;

对于 100%的数据,有 1 ≤ n ≤1,000,0 < a、b < 10000。

分析:
求最大金币数的最小值,很容易让人想到二分,但是仔细一想不满足单调性,正解要用贪心做。贪心方案:按左边乘右边从小到大排序。
原因:我们设需要交换的两个大臣左右边为a1,b1,a2,b2;如果不交换的话,后面那个大臣为tot(前面累加的)*a1/b2,否则为tot*b1/a2,要想让不交换时小,a1/b2就要小于b1/a2,化简后为a1*b1<a2*b2,并且显然后面的大于前面的,所以贪心方案成立。
然后就是恶心的高精度了!!!

代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define M 5010
using namespace std;
int kingz,kingy;int n,a1[M],b1[M];
struct node1
{
    int zuo,you;
};node1 e[M];
struct node2
{
    int p[M],l;
    node2()
    {
        memset(p,0,sizeof(p));
        l=0;
    }
};node2 ans,p;
int read()
{
    char c=getchar();int num=0,flag=1;
    while(c<'0'||c>'9'){if(c=='-')flag=-1;c=getchar();}
    while(c>='0'&&c<='9'){num=num*10+c-'0';c=getchar();}
    return num*flag;
}
bool cmp(const node1&x,const node1&y)
{
    return x.zuo*x.you<y.zuo*y.you;
}
node2 cheng(node2 a,int b)
{
    memset(a1,0,sizeof(a1));
    memset(b1,0,sizeof(b1));
    node2 c;
    int len=a.l;
    for(int i=1;i<=a.l;i++)a1[i]=a.p[len-i+1];
    for(int i=1;i<=len;i++)
    {
        b1[i]+=a1[i]*b;
        b1[i+1]+=b1[i]/10;
        b1[i]%=10;
    }
    while(b1[len+1]>=10)
    {
        b1[len+2]=b1[len+1]/10;
        b1[len+1]%=10;
        len++;
    }
    if(b1[len+1])len++;c.l=len;
    for(int i=1;i<=len;i++)c.p[i]=b1[len-i+1];
    return c;
}
node2 chu(node2 a,int b)
{
    memset(a1,0,sizeof(a1));
    node2 c;
    int x=0;
    for(int i=1;i<=a.l;i++)
    {
        a1[i]=(x*10+a.p[i])/b;
        x=x*10+a.p[i]-a1[i]*b;
    }
    int len=1;
    while(!a1[len]&&len)len++;
    for(int i=len;i<=a.l;i++)
      c.p[++c.l]=a1[i];
    return c;
}
node2 big(node2 a,node2 b)
{
    node2 c;bool flag=false;
    if(a.l<b.l)flag=true;
    if(a.l==b.l)
    {
        for(int i=1;i<=a.l;i++)
          if(a.p[i]<b.p[i]){flag=true;break;}
    }
    if(flag)
    {
        c.l=b.l;
        for(int i=1;i<=c.l;i++)c.p[i]=b.p[i];
    }
    else
    {
        c.l=a.l;
        for(int i=1;i<=c.l;i++)c.p[i]=a.p[i];
    }
    return c;
}
void init(int x)
{
    memset(a1,0,sizeof(a1));
    int len=0;
    while(x)
    {
        a1[++len]=x%10;
        x/=10;
    }
    p.l=len;
    for(int i=1;i<=len;i++)
      p.p[len-i+1]=a1[i];
}
int main()
{
    scanf("%d",&n);
    kingz=read();kingy=read();
    for(int i=1;i<=n;i++)
      e[i].zuo=read(),e[i].you=read();
    sort(e+1,e+n+1,cmp);
    init(kingz);
    for(int i=1;i<=n;i++)
    {
        node2 ch=chu(p,e[i].you);
        ans=big(ans,ch);
        p=cheng(p,e[i].zuo);
    }
    for(int i=1;i<=ans.l;i++)
      printf("%d",ans.p[i]);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/harden/p/5785173.html