首页 > 编程语言 >C++编程-贪心算法2

C++编程-贪心算法2

时间:2024-10-20 11:53:40浏览次数:14  
标签:int 系统 编程 高度 C++ 导弹 拦截 例题 贪心

目录

先言

例题三:删数问题(NOI1994)

题目描述

算法分析

标准程序 - 字符串String

例题四:拦截导弹问题

题目描述

算法分析

主要框架(标准程序)

例题五:活动选择

题目描述

算法分析

标准程序


先言

今天讲贪心算法的第3~5例题

例题三:删数问题(NOI1994)

题目描述

【题目描述】

  输入一个高精度的正整数N,去掉其中任意S个数字后剩下的数字按原左右次序组成一个新的正整数。编程对给定的N和S,寻找一种方案使得剩下的数字组成的新数最小。

       输出新的正整数。(N不超过240位)输入数据均不需判错。

【输入】

       n

       s

【输出】

       最后剩下的最小数。

【样例输入】

       175438

       4

【样例输出】

       13

算法分析

       由于正整数n的有效数位为240位,所以很自然地采用字符串类型存贮n。那么如何决定哪s位被删除呢?是不是最大的s个数字呢?显然不是,大家很容易举出一些反例。为了尽可能逼近目标,我们选取的贪心策略为:每一步总是选择一个使剩下的数最小的数字删去,即按高位到低位的顺序搜索,若各位数字递增,则删除最后一个数字;否则删除第一个递减区间的首字符,这样删一位便形成了一个新数字串。然后回到串首,按上述规则再删下一个数字。重复以上过程s次为止,剩下的数字串便是问题的解了。

例如:n=175438

            s=4

            删数的过程如下:

                 n=175438      //删掉7

                     15438        //删掉5

                     1438          //删掉4

                     138            //删掉8

                     13              //解为13

       这样,删数问题就与如何寻找递减区间首字符这样一个简单的问题对应起来。不过还要注意一个细节性的问题,就是可能会出现字符串串首有若干0的情况,甚至整个字符串都是0的情况。按以上贪心策略编制的程序框架如下

   输入n,s;
   for (i=1;i<=s;++i) {              //一共要删除s个字符  
      for ( j=0;j<len-1;++j )        //从串首开始找,len是n的长度
        if ( n[j]>n[j+1] ) {            //找到第一个符合条件的 
           for (k=j;k<len-1;++k)   //删除字符串n的第j个字符,后面字符往前整
                n[k]=n[k+1];
           break;
        }
      --len;                                  //长度减1
   }
   输出n;                                //删去串首可能产生的无用零

标准程序 - 字符串String

#include<string>
#include<iostream>
using namespace std;

int main() {
	int s;
	string n;
	cin >> n >> s;
	for (int i; i = 0, s--; n.erase(i, 1)) 
	   while (i < n.size() && n[i] <= n[i+1])
	      ++i;
	while (n.size() > 1 && n[0] == '0')
	  n.erase(0, 1);
	cout << n << endl;
	return 0;
}

例题四:拦截导弹问题

题目描述

    某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统,但是这种拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭,由于该系统还在试用阶段。所以一套系统有可能不能拦截所有的导弹。

    输入导弹依次飞来的高度(雷达给出的高度不大于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

算法分析

  按照题意,被一套系统拦截的所有导弹中,最后一枚导弹的高度最低。设:

  k为当前配备的系统数;

  l[k]为被第k套系统拦截的最后一枚导弹的高度,简称系统k的最低高度(1≤k≤n)。

  我们首先设导弹1被系统1所拦截(k←1,l[k]←导弹1的高度)。然后依次分析导弹2,…,导弹n的高度。

  若导弹i的高度高于所有系统的最低高度,则断定导弹i不能被这些系统所拦截,应增设一套系统来拦截导弹I(k←k+1,l[k]←导弹i的高度);若导弹i低于某些系统的最低高度,那么导弹i均可被这些系统所拦截。究竟选择哪个系统拦截可使得配备的系统数最少,我们不妨采用贪心策略,选择其中最低高度最小(即导弹i的高度与系统最低高度最接近)的一套系统p(l[p]=min{l[j]|l[j]>导弹i的高度};l[p]←导弹i的高度)(1≤j≤k)。这样可使得一套系统拦截的导弹数尽可能增多。

  依次类推,直至分析了n枚导弹的高度为止。此时得出的k便为应配备的最少系统数。

主要框架(标准程序)

参考程序主要框架如下:

  k=1; l[k]=导弹1的高度;
  for (i=2; i<=n; ++i)
  {
       p=0;
     for (j=1; j<=k; ++j)
               if (l[j]>=导弹i的高度) { if (p==0) p=j;
                                   else if (l[j]<l[p]) p=j;
                } //贪心
    if (p==0) { ++k; l[k]=导弹i的高度; }                      //增加一套新系统       
    else l[p]=导弹i的高度;                                             //贪心,更新第p套系统的最低高度
  }

输出应配备的最少系统数K。

例题五:活动选择

题目描述

      学校在最近几天有n个活动,这些活动都需要使用学校的大礼堂,在同一时间,礼堂只能被一个活动使用。由于有些活动时间上有冲突,学校办公室人员只好让一些活动放弃使用礼堂而使用其他教室。   
      现在给出n个活动使用礼堂的起始时间begini和结束时间endi(begini<endi),请你帮助办公室人员安排一些活动来使用礼堂,要求安排的活动尽量多。 

【输入】 第一行一个整数n(n<=1000);      
    接下来的n行,每行两个整数,第一个begini,第二个是endi (begini<endi<=32767)
【输出】 输出最多能安排的活动个数。
【样例输入】
  11
  3 5
  1 4
  12 14
  8 12
  0 6
  8 11
  6 10
  5 7
  3 8
  5 9
  2 13
【样例输出】
  4

算法分析

    • 算法模型:给n个开区间(begini,endi), 选择尽量多的区间, 使得两两不交。

    • 做法: 首先按照end1<=end2<…<=endn的顺序排序,依次考虑各个活动, 如果没有和已经选择的活动冲突, 就选; 否则就不选。

    • 正确性: 如果不选end1, 假设第一个选择的是endi,则如果endi和end1不交叉则多选一个end1更划算; 如果交叉则把endi换成end1不影响后续选择。

标准程序

(省略前部)
int n,begin[1001],end[1001];
void init()
{
    cin>>n;
    for(int i=1;i<=n;i++)   
        cin>>begin[i]>>end[i];
}
void qsort(int x,int y)
{ 
    int i,j,mid,t;
    i=x; j=y; mid=end[(x+y)/2];
    while(i<=j)
    { 
         while(end[i]<mid) ++i;
         while(end[j]>mid) --j;
         if(i<=j)
         { 
              t=end[j]; end[j]=end[i]; end[i]=t;
              t=begin[j]; begin[j]=begin[i]; begin[i]=t;
              ++i;j; 
         }
    }
    if(x<j) qsort(x,j);
    if(i<y) qsort(i,y);
}
void solve()
{ 
   int ans=0;
   for(int i=1,t=-1;i<=n;++i)//在初始化循环变量的同时,初始化t。
                             //令t=-1可以使第一个区间与其他区间的操作相同 
     if(begin[i]>=t) 
     { //当前活动开始时间与之前选择的活动结束时间不冲突,就接受当前活动
        ++ans;t=end[i]; 
     } 
   cout<<ans<<endl;
}

int main()
{
    init();
    qsort(1,n);
    solve();
    return 0;
}

标签:int,系统,编程,高度,C++,导弹,拦截,例题,贪心
From: https://blog.csdn.net/weixin_68261272/article/details/143090504

相关文章

  • c++跑酷(技能升级版,升级火,镖,水)
    #include<bits/stdc++.h> #include<windows.h>#include<stdio.h>#include<conio.h>#include<time.h>#defineNorif(B[b].x<5)B[b].x=5;#defineOut1Bx1-Bvx1<=6||Bx1-Bvx1>=28||By1-Bvy1<=7||By1-Bvy1>=27#defineOut......
  • 用C++实现自己的智能指针:深入探讨内存管理与RAII模式
    解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界C++中的内存管理一直以来是程序员的一个难点,尤其是在处理动态内存分配时。智能指针(如std::unique_ptr和std::shared_ptr)通过RAII(资源获取即初始化)的设计理念,极大地简化了动态内存的管理,减少了内存泄漏的风险。然......
  • 用C++编写一个简单的游戏引擎:从游戏循环到物理与渲染的全面解析
    解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界构建一个基础的2D游戏引擎是一项富有挑战性但极具学习价值的任务。本文将通过从零开始的方式,逐步讲解如何使用C++开发一个简单的游戏引擎。内容涵盖了游戏引擎的核心架构设计,包括游戏循环、物理引擎和图形渲染等......
  • 编程小白如何成为大神:大学新生的最佳入门攻略
    编程已成为当代大学生的必备技能,但面对众多编程语言和学习资源,新生们常常感到迷茫。以下是大学新生入门编程的最佳路径,帮助你为大学生活和未来职业发展打下坚实基础。方向一:编程语言选择1.Python特点:语法简洁易懂,适合初学者;拥有丰富的库和框架。应用领域:数据分析、人工智......
  • 详解UDP-TCP网络编程
    目录UDP数据报套接字编程API代码示例--(回显)单个客户端UdpEchoServerUdpEchoClientUdpDictServer(词典)将服务端程序部署到云服务器上TCP流套接字编程API长短链接代码示例--(回显)多个客户端TcpEchoServerTcpEchoClientUDP数据报套接字编程APIDatagramSoc......
  • C++初阶
     目录一.命名空间1.命名空间定义2.命名空间使用二.C++输入&输出三.缺省参数四.函数重载五.引用1.常引用2.传值、传引用效率比较3.引用和指针的区别4.引用和指针的不同点:小知识点:六.内联函数七.auto关键字(C++11)1.auto的使用细则八.基于范围的for循环(C++1......
  • C++ -string -常见用法4
    博客主页:【夜泉_ly】本文专栏:【C++】欢迎点赞......
  • 【C++修行之道】vector
     一、vector的介绍1.1vector的介绍vector的文档介绍1.vector是表示可变大小数组的序列容器。2.就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的......
  • C++的RAII原则
    C++的RAII原则内容ResourceAcquisitionIsInitialization(RAII)isacoreprogrammingconceptinC++(andotherresource-managedlanguages).Itensuresthatresources,suchasmemory,filehandles,ornetworkconnections,areacquiredandreleasedproperlyb......
  • 深入浅出之cuda编程概念
    CUDA(ComputeUnifiedDeviceArchitecture)是NVIDIA推出的一种用于通用并行计算的编程模型和编程接口。它允许开发者利用NVIDIAGPU的强大计算能力来加速应用程序。CUDA编程涉及使用CUDAC/C++或CUDAFortran等语言编写代码,这些代码可以在GPU上并行执行,从而显著提高计算性能。......