删数问题-贪心

题目:html

键盘输入一个高精度的正整数N(不超过250位) ,去掉其中任意k个数字后剩下的数字按原左右次序将组成一个新的正整数。ios

编程对给定的Nk,寻找一种方案使得剩下的数字组成的新数最小。算法

 

算法思路:编程

要从正整数中删除k个数字,能够采起一步步来删的策略,每一次删除一个数字,使得当前获得的数字是最小的,执行k步后,即获得最后的结果。函数

经过子问题的最优解来获得整个问题的最优解,就是贪心的思想。spa

例如:7122145这个数字,若是k=3,第一次删除的应该是7,获得122145;第二次删除的应该是5,获得12214;第三次删除的应该是4,获得1221.code

 

经过观察,能够发现每次删除的数字有这样的规律:htm

都是整个数字中递减区间的第一个数字,若是整个数中没有递减区间,就删除最后一个数字,由于要想留下的数字最小,它的高位确定要尽量小,blog

这样删除的方法,在当前次看来都是最优的,咱们把降序区间的第一个数删掉,就能够让后面比他小的数前进一个高位,那么数字也就变小了,ci

若是咱们删除了这个最优数字前面的数,那么这个比较大的数字就前进了一个高位,反而让数字变大了,

一样的,若是咱们删除这个数后面的也很大的数字,虽然能让小的数也前进一个高位,可是它自己处的位置也很低,显然没有让利益最大化。

 

上代码:

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;  4 int main() {  5     string n;  6     int k;  7     cin >> n;  8     cin >> k;  9     while (k != 0) { 10         int flag = 0; 11         for (int i = 0; i < n.length()-1; i++) { 12             if (n[i] > n[i + 1]) { 13                 n.erase(i, 1); 14                 flag = 1; 15                 break; 16  } 17  } 18         //若是数字都是单调递增的,就删除最后一个
19         if(!flag) n.erase(n.length() - 1, 1); 20         k--; 21  } 22     int i = 0; 23     if (n == "0") { 24         cout << n; 25         return 0; 26  } 27     //将首位的0去掉
28     while (n[i] == '0') { 29         i++; 30  } 31     for (int j = i; j < n.length(); j++) { 32         cout << n[j]; 33  } 34 
35     return 0; 36 }

 

其中,string中的erase()函数的用法在个人另外一篇博客中有总结。

相关文章
相关标签/搜索