算法第四章上机实验报告

算法第四章上机实验报告

一、实验题目

4-2 删数问题 (30 分)

给定n位正整数a,去掉其中任意k≤n 个数字后,剩下的数字按原次序排列组成一个新的正整数。对于给定的n位正整数a和正整数 k,设计一个算法找出剩下数字组成的新数最小的删数方案。如果数字最前面有0不输出。

输入格式:

第 1 行是1 个正整数 a。第 2 行是正整数k。

输出格式:

输出最小数。

输入样例:

在这里给出一组输入。例如:

178543

4

结尾无空行

5001

1

结尾无空行

123456

2

结尾无空行

109

1

结尾无空行

输出样例:

在这里给出相应的输出。例如:

13

结尾无空行

1

结尾无空行

1234

结尾无空行

9

结尾无空行

 

二、贪心算法选择

  依次删除第一段递增子序列的最后一个值

  贪心策略分析:

         按题目所给的第一个例子来看,删除178543中的四个数字,得到最小的两位数。按照常规思维我们会选择其中四个较大的数字进行删除,在这个例子中也可以得到正确答案。但是如果所给的数是305462,删除一个数字,选择最大的数6,所得的数为30542,而如果删除5,所得的数为30462,很明显,此时30542>30462,因此证明选择较大数字进行删除的贪心策略是行不通的。原因在于题目所给的条件:剩下的数字按原次序排列组成一个新的正整数。所以在305462这个数中,即使6是这个数最大的那个数字,但是因为不能打乱顺序,5所在的位次比6高,删除5后的数字会比删除6后的数字小。而5正好是这个数中递增序列的最后一个数字。所以此题的贪心策略是依次删除第一段递增子序列的最后一个值。经检验,此方法可行。

 

三、题目代码

  

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

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char** argv) {
    char a[1000];
    int k;
    int len; 
    cin >> a >> k;
    len = strlen(a);
    for(int i = 0; i < k; i++)
    {
        for(int j = 0; j < len; j++)
        {
            if(a[j + 1] > a[j])
                continue;
            else
            {
                for(int i = j; i < len; i++)
                {
                    a[i] = a[i + 1];
                }
                len--;
                break;
            }
        }
    }
    
    bool flag = false;
    
    for(int i = 0; i < len; i++)
    {
        if(a[i] != '0')
            flag = true;
        if(flag)
            cout << a[i];
    }
    return 0;
}

 

四、算法时间复杂度

  O(n)= n^2

 

五、对贪心算法的理解

  贪心算法需要找到最优解,而往往有时候我们习以为常的最优解决方案并不是题目的最优解,因此需要进行多次举例尝试,避免出现找错贪心算法策略的问题。找出贪心算法策略后,也要反复进行验证。

posted @ 2021-11-17 22:06  Nefertari0716  阅读(11)  评论(0编辑  收藏  举报