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 }

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

 

转载于:https://www.cnblogs.com/KakagouLT/p/4694278.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip
综合小区管理系统管理系统按照操作主体分为管理员和用户。管理员的功能包括报修管理、车位管理、车位分配管理、出入管理、字典管理、房屋管理、物业费缴纳管理、公告管理、物业人员投诉管理、我的私信管理、物业人员管理、用户管理、管理员管理。用户的功能包括管理部门以及部门岗位信息,管理招聘信息,培训信息,薪资信息等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 综合小区管理系统管理系统可以提高综合小区管理系统信息管理问题的解决效率,优化综合小区管理系统信息处理流程,保证综合小区管理系统信息数据的安全,它是一个非常可靠,非常安全的应用程序。 管理员权限操作的功能包括管理公告,管理综合小区管理系统信息,包括出入管理,报修管理,报修管理,物业费缴纳等,可以管理操作员。 出入管理界面,管理员在出入管理界面中可以对界面中显示,可以对招聘信息的招聘状态进行查看,可以添加新的招聘信息等。报修管理界面,管理员在报修管理界面中查看奖罚种类信息,奖罚描述信息,新增奖惩信息等。车位管理界面,管理员在车位管理界面中新增。公告管理界面,管理员在公告管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值