【贪心+排序】国王游戏

【贪心+排序】国王游戏

Time Limit: 1000MS
Memory Limit: 131072KB

Description
恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 n 位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。
国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。




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




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




Sample Input
3
1 1
2 3
7 4
4 6




Sample Output
2




Hint
【输入输出样例说明】按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。



Source
noip2012

这题数据很水

暴搜20分

我没想到以左右手的成绩为关键字排序

真弱真悲伤

我以左手为关键字排序错误贪心加上暴搜得了30分

正解:

我们先考虑只有两个人的情况

第一个人:l/r1   l*l1/r2;很明显l*l1/r2>l/r1;

第二个人:l/r2   l*l2/r1;  很明显l*l2/r1>l/r2;

比较max(l1/r2,l2/r1)=(l1*r1,l2*r2);

所以可以用贪心以左右手的乘积为顺序然后依次枚举


TOT 我高精度又TM写丑了

竟然三个点超时

 

但是数据很水

只要枚举最后一个人与第一个人

还是没理解透彻

能证明枚举最后一个人与第一个人是对的额

 

所以领袖说的很对 noip的题数据很水

 

所以我还是先练练高精度吧

# include<stdio.h>
# include<cstring>
# include<iostream>
# include<vector>
# include<algorithm>
using namespace std;
const int maxn=10000;
typedef long long LL;
char tb[maxn];
struct node{
    LL  l;
    LL  r;
}edge[1000+10];
LL  gl,gr,n,Min=-0x7fffffff,MIN=0x7fffffff;
LL  vis[maxn],a[maxn],c[maxn],str[maxn];
LL  cmp(const node &A,const node &B){
    return A.l*A.r<B.l*B.r;
}
void check(){
    if(a[0]<str[0])return;
    else if(a[0]>str[0]){str[0]=a[0];for(int i=1;i<=a[0];i++)str[i]=c[i];}
    else if(a[0]==str[0])
    for(int i=a[0];i>=1;i--)
    if(c[i]>str[i]){
    for(int i=1;i<=a[0];i++)str[i]=c[i];
    break;
    }
}
void mul(LL x){
  LL i,m=0;
  for (i=1;i<=a[0];i++){
    m=m+a[i]*x;
    a[i]=m%10;
    m=m/10;
  }
  while(m!=0){
    a[0]++;
    a[a[0]]=m%10;
    m=m/10;
  }
}
void di(int b){
    LL  x=0;
    for(LL i=a[0];i>=1;i--){
        c[i]=(x*10+a[i])/b;
        x=(x*10+a[i])%b;
    }
    while(c[a[0]]==0&&a[0]!=1)a[0]--;
}
void init(){
    cin>>n;
    cin>>gl>>gr;
    for(LL  i=1;i<=n;i++)
    scanf("%I64d%I64d",&edge[i].l,&edge[i].r);
}
void yy(){
    LL x1=-0x7fffffff,x2=-0x7fffffff;
    sort(edge+1,edge+n+1,cmp);
    for(LL  i=n;i<=n;i++){
        memset(a,0,sizeof(a));
        memset(c,0,sizeof(c));
        LL cur=0;
        LL t=gl;
        while(t!=0){a[++cur]=t%10;t=t/10;}
        a[0]=cur;
        for(LL  j=1;j<i;j++)
        mul(edge[j].l);
        di(edge[i].r);
        check();
    }
        for(LL  i=1;i<=1;i++){
        memset(a,0,sizeof(a));
        memset(c,0,sizeof(c));
        LL cur=0;
        LL t=gl;
        while(t!=0){a[++cur]=t%10;t=t/10;}
        a[0]=cur;
        for(LL  j=1;j<i;j++)
        mul(edge[j].l);
        di(edge[i].r);
        check();
    }
    for(int i=str[0];i>=1;i--)
    cout<<str[i];
}
void dfs(LL  cur,LL  much){
    if(cur==n){
        LL  k;
        for(LL  i=1;i<=n;i++)
        if(!vis[i]){k=i;break;}
        MIN=min(MIN,much/edge[k].r);
        return;
    }
    for(LL  i=1;i<=n;i++)
    if(!vis[i]){
        vis[i]=1;
        dfs(cur+1,much*edge[i].l);
        vis[i]=0;
    }
}
void easy(){
    dfs(1,gl);
    cout<<MIN;
}
int  main(){
    init();
    //easy();
     yy();
    return 0;
}

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。