zoukankan      html  css  js  c++  java
  • NOIP 2012 提高组 DAY1 T2 国王游戏

    题目描述

    恰逢 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。

    NOIP 2012 提高组 第一天 第二题

      贪心策略 :左右手乘积最小排在前

      

      证:x1  y1

        x2  y2  

        ...   ...

        -----------  

        xa  ya

        xb  yb

        ----------

        ...  ...

        按 (xi*yi) 从小到大排序

        如果相邻的两个人交换位置,只会影响到这两个人的值,不会影响他人

        在xa之前的乘积是一定的 我们假设为 S

        xa,ya 和xb,yb交换前

          xa 获得的金币 为(S/ya) 记为 X

        xb 获得的金币 为((S*xa)/yb) 记为 Y

        xa,ya 和xb,yb交换后

        xa 获得的金币 为(S/yb) 记为 P

        xb 获得的金币 为((S*xb)/ya) 记为 Q

        结果是找 max(X,Y) 和max(P,Q)之中小的那个数

        两个max同乘yayb之后

        X 为(S*yb)   Y为 (S*xa*ya)

        P 为(S*ya)   Q为 (S*xb*yb)

        由于要让最大值尽量小 那么

           因为,xa*ya <= xb*yb

        所以,S*xa/yb<= S*xb/ya

        又因为,S/yb <= S*xa/yb

        所以,ans2=S* xb/ya

        ans1=max{S/ya,S*xa/yb}

        所以,ans1<=ans2

        所以我们可以得出 xi*yi 最小时策略最优

      1 /*
      2     一道贪心+高精 
      3     贪心策略简单 就是找左右手乘积最小的排在前边
      4     高精恶心 我不想再见这道题第二次
      5 */
      6 #include<cstdio>
      7 #include<cstring>
      8 #include<iostream>
      9 #include<algorithm>
     10 #define MAXN 5010
     11 #define LL long long
     12 
     13 using namespace std;
     14 
     15 struct node {
     16     int a,b;
     17     LL sum;
     18 };
     19 node e[MAXN];
     20 
     21 int ans[MAXN],ans1[MAXN],b[MAXN];
     22 
     23 int n,p;
     24 
     25 char s[MAXN];
     26 
     27 inline void read(int &x) {
     28         int f=1;x=0;char c=getchar();
     29        while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
     30         while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-48;c=getchar();}
     31        x=x*f;
     32 }
     33 
     34 inline bool cmp(const node x,const node y) {
     35     return x.sum<y.sum;
     36 }
     37 
     38 inline void chu(int x) {
     39     b[0]=0;
     40     memset(b,0,sizeof b);
     41     LL k=0;
     42     for(int i=ans1[0];i>=1;i--) {
     43         k=k*10+ans1[i];
     44         if(k>=x) {
     45             if(b[0]==0) b[0]=i;
     46             b[i]=k/x;
     47             k%=x;
     48         }
     49     }
     50 }
     51 
     52 inline void compare() {
     53     if(b[0]>ans[0]) {
     54         for(int i=0;i<=MAXN;i++) ans[i]=b[i];
     55         return;
     56     }
     57     else if(b[0]==ans[0]) {
     58         for(int i=ans[0];i>=1;i--) {
     59             if(b[i]>ans[i]) {
     60                 for(int j=0;j<=MAXN;j++) ans[j]=b[j];
     61                 return;
     62             }
     63         }
     64     }
     65 }
     66 
     67 inline void mul(int x) {
     68     LL k=0;
     69     memset(b,0,sizeof b);
     70     for(int i=1;i<=ans1[0];i++) {
     71         b[i]+=ans1[i]*x+k;
     72         b[i+1]+=b[i]/10;
     73         b[i]=b[i]%10;
     74     }
     75     for(b[0]=ans1[0];b[b[0]+1];) {
     76         b[++b[0]+1]+=b[b[0]]/10;
     77         b[b[0]]=b[b[0]]%10;
     78     }
     79     for(int i=0;i<MAXN;i++) ans1[i]=b[i];
     80 }
     81 
     82 int main() {
     83     read(n);
     84     scanf("%s",s+1);
     85     for(int i=strlen(s+1);i>=1;i--) ans1[++ans1[0]]=s[i]-'0';
     86     read(p);
     87     for(int i=1;i<=n;i++) {
     88         read(e[i].a);
     89         read(e[i].b);
     90         e[i].sum=e[i].a*e[i].b;
     91     }
     92     sort(e+1,e+1+n,cmp);
     93     for(int i=1;i<=n;i++) {
     94         chu(e[i].b);
     95         compare();
     96         mul(e[i].a);
     97     }
     98     for(int i=ans[0];i>=1;i--) printf("%d",ans[i]);
     99     printf("
    ");
    100     return 0;
    101 }
    代码


    作者:乌鸦坐飞机
    出处:http://www.cnblogs.com/whistle13326/
    新的风暴已经出现 怎么能够停止不前 穿越时空 竭尽全力 我会来到你身边 微笑面对危险 梦想成真不会遥远 鼓起勇气 坚定向前 奇迹一定会出现

     
  • 相关阅读:
    HttpServletRequest request 获取form参数的两种方式
    mysql中计算两个日期的时间差函数TIMESTAMPDIFF用法
    Better exception message for missing @RequestBody method parameter
    下载Xcode历史版本方法
    CGLib与JDK的动态代理
    LeetCode: Longest Consecutive Sequence [128]
    POJ训练计划2777_Count Color(线段树/成段更新/区间染色)
    JBoss AS 7性能调优(三)
    java的Future使用方法
    Redis学习资源
  • 原文地址:https://www.cnblogs.com/whistle13326/p/6822167.html
Copyright © 2011-2022 走看看