zoukankan      html  css  js  c++  java
  • NOIP2012 国王游戏

    2国王游戏

    (game.cpp/c/pas)

    【问题描述】

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

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

    【输入】

    输入文件为 game.in。

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

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

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

    【输出】

           输出文件名为 game.out。

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

    【输入输出样例】

    game.in

    game.out

    3

    1     1

    2     3

    7 4

    4 6

    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。

     【思路】

      贪心+sort+高精单精。

      设i之前的左手之积为X,对于i有左右手Li Ri 对于排在其后的j有左右手Lj Rj 当满足(X*Li)/Rj >(X*Lj)/Ri即满足Li*Ri>Lj*Rj时交换ij的位置显然更优,将数据LR之积递增排序就是最优方案,X会很大所以用到高精。

     【代码】

    //思路很快想到 但是高精度优化用了很长世间 还是生疏了 
    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int maxn = 1000+10;
    struct Node{
        int a,b;
        bool operator <(const Node& rhs) const{
         return (a*b<rhs.a*rhs.b );  
        }
    };
    Node nodes[maxn];
    struct gaojing{
        int A[10000];
        void init() {
            memset(A,0,sizeof(A)); //memset<-0
            A[0]=1;  //长度 
            A[1]=1;
        }
        void cheng(int x) {
            for(int i=1;i<=A[0];i++) A[i]=A[i]*x;  //先乘后进位 
            for(int i=1;i<=A[0];i++) {
                A[i+1]+=A[i]/10;
                A[i]%=10;
            }
            int tmp=0;
            if(A[A[0]+1]) {
                A[0]++;
                while(tmp=A[A[0]]/10,tmp) {
                    A[A[0]+1]=tmp;
                    A[A[0]]%=10;
                    A[0]++;
               }
            }
        }
        void chu(int x) {
            int tmp=0;
            for(int i=A[0];i;i--) {
                int k=A[i];
                A[i]=(tmp*10+k)/x;
                tmp =(tmp*10+k)%x;
            }
            while(!A[A[0]]) A[0]--;
        }
        void print() {
            for(int i=A[0];i;i--) printf("%d",A[i]);
        }
    };
    gaojing ans,rec;
    gaojing max_gaojing(gaojing a,gaojing b){
        if(a.A[0]>b.A[0]) return a; else if(a.A[0]<b.A[0]) return b;
        for(int i=a.A[0];i;i--)  {  //从最高位开始比较 
         if(a.A[i]>b.A[i]) return a;
         if(a.A[i]<b.A[i]) return b;
        }
        return a; 
    }
    
    int n;
    int main() {
        scanf("%d",&n);
        for(int i=0;i<=n;i++) scanf("%d%d",&nodes[i].a,&nodes[i].b);
        sort(nodes+1,nodes+n+1);
        rec.init(); ans.A[0]=0;
        for(int i=1;i<=n;i++) { //高精与单精相运算 
            rec.cheng(nodes[i-1].a); 
            gaojing k=rec; k.chu(nodes[i].b);
            ans=max_gaojing(ans,k);
        }
        ans.print();
        return 0;
    }
  • 相关阅读:
    算法竞赛入门经典第一章习题解答
    程序实现求int类型和double类型的最大最小值范围
    程序实现求int类型和double类型的最大最小值范围
    程序实现求int类型和double类型的最大最小值范围
    程序实现求int类型和double类型的最大最小值范围
    机器狗组装费用 南邮NOJ 1076 优先权队列
    【HDOJ】2604 Queuing
    【HDOJ】1208 Pascal's Travels
    【HDOJ】4857 逃生
    【HDOJ】2510 符号三角形
  • 原文地址:https://www.cnblogs.com/lidaxin/p/4859310.html
Copyright © 2011-2022 走看看