【刷题第八天】贪心——C++

【题目描述】

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

输出新的正整数。(n不超过240位)

输入数据均不需判错。

【输入】

n

s

【输出】

最后剩下的最小数。

【输入样例】

175438
4

【输出样例】

13

算法分析:
(1)175438中取出7
(2)15438中取出5
(3)1438中取出4
(4)138中取出8
这里很明显就能看出来取出7、5、4的时候前面都是升序,如17是升序后面就降序了,15是升序,14是升序。另外一种情况就是全部是升序,那就只要将后面指定的个数取走就好了。
 1 #include <iostream>
 2 using namespace std;
 3 int main() {
 4     char n[240];
 5     char t;
 6     int s, len = 0, d = 0, min, k, di, flag = 1, a;
 7     cin >> n;
 8     cin >> s;
 9     while (n[len] != '\0')
10     {
11         len++;
12     }
13     di = len - s;
14     while (s>0) {                 
15         k = 0;
16         for (a = 0; a < len; a++)
17         {
18             if (n[a] > n[a+1] && a!=len-1) {                //这是用来判断什么时候变成降序,另外后面的条件是不让最后一个数和结束符一起比较(主要用来判断这些数是不是全是升序)
19                 k = a;
20                 break;
21             }
22         }
23         if (k == 0 && a >= len && len > di) {               //如果这里全是升序,那就直接删去后面的指定个数即可
24             len = di;
25             break;                                           //这个一定要写
26         }
27         else {
28             for (int j = k + 1; j < len; j++)             //删去指定的数。
29             {
30                 n[j - 1] = n[j];
31             }
32             len--;
33         }
34         s--;
35     }
36     flag = 1;
37     for (int i = 0; i < len; i++)
38     {
39         if (n[i] == '0' && i < len - 1 && flag == 1) {                //这里就是判断第一个数是不是等于0
40             continue;
41         }
42         else {
43             cout << n[i];
44             flag = 0;
45         }
46         
47     }
48 
49     
50     return 0;
51 }

 

【题目描述】

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

输入导弹依次飞来的高度(雷达给出的高度不大于30000的正整数)。计算要拦截所有导弹最小需要配备多少套这种导弹拦截系统。

【输入】

n颗依次飞来的高度(1≤n≤1000)。

【输出】

要拦截所有导弹最小配备的系统数k。

【输入样例】

389 207 155 300 299 170 158 65

【输出样例】

2

【提示】

输入:导弹高度: 4  3  2

输出:导弹拦截系统k=1

算法分析:这道题目第一感觉有和上一题有类似点,刚开始的时候确实想到直接用升降序的方法,但是是错的。输入样例看着是用升降法是可以做的,但很明显554 345 75 178 51 64 28 18 51 51 542 17
这个用升降法是错的。这个是有三个系统的,我用三条线来表示:

(1)554——345——75——51——28——18——17

(2)178——64——51——51

(3)542

554进入(1),345进入(1),75进入(1),178进入(2),51进入(1){这里很明显就应该进入(1)中,因为和(2)相比离(1)更近,如果选(2)那就不是最优解},64进入(2),28进入(1),18进入(1),51进入(2),51进入(2){不超过即可},542进入(3),17进入(1)

过程就是这样,我想到的是另外取一个数组来放置几条不同的线,根据差的大小放置到各个线中,那么最后这个数组的长度就是系统的个数。

 1 #include <iostream>
 2 using namespace std;
 3 int main() {
 4     int n[1000], a = 1, len = 0, m[1000], m_len = 0, min;
 5     while (cin >> n[len])                 //ctrl+Z之后回车就是输入了
 6     {
 7         len++;
 8     }
 9     for (int i = 0; i < len; i++)
10     {
11         min = 30000;                     //这是用来看和谁的差最小
12         if (m_len == 0) {                //如果没有任何一条线就创造一条
13             m[m_len] = n[i];
14             m_len++;
15         }
16         else {
17             for (int j = 0; j < m_len; j++)              //循环各个线,选择相应的线插入
18             {
19                 if (m[j] - n[i] >= 0 && m[j] - n[i] < min) {                //这个是保证差是正数(如果全是负数就要创造新的线),找到最小的差的线
20                     min = m[j] - n[i];
21                     a = j;
22                 }
23             }
24      
25             if (min == 30000) {                    //如果没有找到就创造新的线
26                 m[m_len] = n[i];
27                 m_len++;
28             }
29             else {                               //找到了就插入
30                 m[a] = n[i];
31             }
32         }
33     }
34     cout << m_len;
35     return 0;
36 }

 

posted @ 2020-07-24 16:57  zym112233  阅读(265)  评论(0)    收藏  举报