zoukankan      html  css  js  c++  java
  • Ka贪心大暴走

    【例4】均分纸牌(NOIP2002
            有 N 堆纸牌,编号分别为 1,2,…, N。每堆上有若干张,但纸牌总数必为 N 的倍数。可以在任一堆上取若干张纸牌,然后移动。
            移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 的堆上;在编号为 N 的堆上取的纸牌,只能移到编号为 N-1 的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。
            现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。
    例如 N=4,4 堆纸牌数分别为:  ① 9 ② 8 ③ 17 ④ 6
            移动3次可达到目的:
            从 ③ 取4张牌放到④(9 8 13 10)->从③取3张牌放到 ②(9 11 10 10)-> 从②取1张牌放到①(10 10 10 10)。
    【输入格式】
           N(N 堆纸牌,1 <= N <= 100)
           A1 A2 … An (N 堆纸牌,每堆纸牌初始数,l<= Ai <=10000)
    【输出格式】
           所有堆均达到相等时的最少移动次数。
    【样例输入】Playcard.in
        4
        9 8 17 6
    【样例输出】Playcard.out
        3
     1 #include <stdio.h>
     2 int main()
     3 {
     4     int i,n,a[105],sum=0;
     5     scanf("%d",&n); //输入纸牌堆数 
     6     for(i=1;i<=n;i++)//输入各堆牌数 弃置0堆 
     7     {
     8         scanf("%d",&a[i]);
     9         sum+=a[i];
    10     }
    11     sum/=n;//求平均数
    12     for(i=1;i<=n;i++)
    13         a[i]-=sum;
    14     //极端情况出现 0 0 0 x x 0 x x 0 0 x 0 0 0 0这种
    15     //现在就见0直接往前挪  不是0把牌丢给右边 负数相当于逆向移牌
    16     //如-3移到1变成0 -2,相当于1移3张给-3 
    17     i=1;
    18     sum=0;
    19     while(i<=n)
    20     {
    21         if(a[i]==0)
    22         {
    23             i++;
    24         }
    25         else
    26         {
    27             a[i+1]+=a[i];
    28             a[i]=0;
    29             i++;
    30             sum++;
    31         }
    32     } 
    33     printf("%d",sum);
    34     return 0;
    35 }
     
     
    【例5】删数问题(NOI94
      输入一个高精度的正整数N,去掉其中任意S个数字后剩下的数字按原左右次序组成一个新的正整数。编程对给定的N和S,寻找一种方案使得剩下的数字组成的新数最小。
           输出新的正整数。(N不超过240位)输入数据均不需判错。
    【输入】
           n
           s
    【输出】
           最后剩下的最小数。
    【样例输入】
           175438
           4
    【样例输出】
           13
    【算法分析】
           由于正整数n的有效数位为240位,所以很自然地采用字符串类型存贮n。那么如何决定哪s位被删除呢?是不是最大的s个数字呢?显然不是,大家很容易举出一些反例。为了尽可能逼近目标,我们选取的贪心策略为:每一步总是选择一个使剩下的数最小的数字删去,即按高位到低位的顺序搜索,若各位数字递增,则删除最后一个数字;否则删除第一个递减区间的首字符,这样删一位便形成了一个新数字串。然后回到串首,按上述规则再删下一个数字。重复以上过程s次为止,剩下的数字串便是问题的解了。
     1 #include <stdio.h>
     2 #include <string.h>
     3 int main()
     4 {
     5     char a[250]; //存长数 
     6     int s,len,k,i=0;  //i为当前选择的位置 
     7     scanf("%s",a);
     8     scanf("%d",&s);
     9     len=strlen(a);
    10     
    11     while(a[i]=='0') i++; //去除首0
    12     //我们现在举个例子,2293620,删4次 
    13     //原理是删第一个单调子段的最大数
    14     //第一个单调子段【相等也视为单调】 229
    15     //删掉9 -> 223620
    16     //删掉3 -> 22620
    17     //删掉6 -> 2220
    18     //删掉第一个2 -> 220
    19     //整个过程就是这样
    20     while(s--)
    21     {
    22         if(a[i]>a[i+1]) //如果是单调递减子段,直接删第一个 
    23         {
    24             i++;
    25         }
    26         else if(a[i]<=a[i+1]) //单调递增子段查找最后一个字符,注意用<= 
    27         {
    28             k=i+1; //i不动,k去找 
    29             while(a[k]<=a[k+1])    k++; //这个k最终到达末尾
    30             while(k+1<len) //从前往后挪,挪到最后一个数是k+1 
    31             {
    32                 a[k]=a[k+1]; 
    33                 k++; 
    34             }
    35             len--; //减少字符长度         
    36         }
    37     }
    38     for(;i<len;i++)
    39         printf("%c",a[i]); 
    40      
    41     return 0;
    42 }
    【例6拦截导弹问题(NOIP1999
            某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统,但是这种拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭,由于该系统还在试用阶段。所以一套系统有可能不能拦截所有的导弹。
           输入导弹依次飞来的高度(雷达给出的高度不大于30000的正整数)。计算要拦截所有导弹最小需要配备多少套这种导弹拦截系统。
    【输入格式】
            n颗依次飞来的高度(1≤n≤1000).
    【输出格式】
           要拦截所有导弹最小配备的系统数k。
    【输入样例】missile.in
           389  207  155  300  299  170  158  65
    【输出样例】missile.out
            2
    【输入输出样例】
    输入:导弹高度: 7  9   6  8  5
    输出:导弹拦截系统K=2
    输入:导弹高度: 4  3  2
    输出:导弹拦截系统K=1
     1 #include <stdio.h>
     2 int main()
     3 {
     4 //    freopen("missile.in","r",stdin);
     5 //    freopen("missile.out","w",stdout);
     6     int flag,sumj=1,height,jacket[1005],i;
     7     scanf("%d",&height);
     8     jacket[0]=height;//先把第一个导弹拦截下来 
     9     while(scanf("%d",&height)==1)//你懂的 
    10     {
    11         flag=1;
    12         for(i=0;i<sumj;i++)
    13         {
    14             if(jacket[i]==height) break;//如果有遇到高度相同自然是不用再准备一套的 
    15             else if(jacket[i]>height)//一个一个找,找到就降低高度并跳出 
    16             {
    17                 jacket[i]=height;
    18                 flag=0;
    19                 break;
    20             }
    21         }
    22         if(flag) //如果上面都没找到就准备新的导弹 
    23         {
    24             sumj++;
    25             jacket[i]=height;
    26         }
    27     }
    28     printf("%d",sumj);
    29     return 0;
    30 }

     这个算法确保了,如果存在一个能拦截此导弹的装置,那么这个装置是所有可拦截装置中高度最小的一个。

  • 相关阅读:
    Spring boot和Spring cloud对应版本兼容问题
    关于 Workbench中 pk,nn,uq,bin,un,zf,ai 的解释
    WebServiceUtil
    POI 导出Excel工具类
    初步了解HTTP协议
    性能测试从零开始-LoadRunner入门
    创新券功能介绍
    Loadrunner 11安装和破解
    《追风筝的人》读后感
    h5学习-webstorm工具的激活
  • 原文地址:https://www.cnblogs.com/KakagouLT/p/4694278.html
Copyright © 2011-2022 走看看