算法第四章上机实验报告
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
代码
#include<bits/stdc++.h> using namespace std; string a; int t; int main() { cin >> a; scanf("%d", &t); while(t--) { int pos = 0;//找每次要删除的位置 char ma = a[0];//从前往后的第一个连续递增序列的末尾,先假设为第一个元素 for(int i = 1; i < a.size(); i++) { if(a[i] < ma)//不再递增,说明前一个值在连续递增序列中是最大的 { pos = i - 1;//记录下标 break; } else ma = a[i];//递增,更新末尾 } a.erase(pos, 1);//删除 从前往后的第一个连续递增序列的末尾 if(a.size()==0) { cout << 0; return 0; } while(a.size() > 1 && a[0]=='0')//删除前导零 { a.erase(0, 1); } } for(int i = 0; i < a.size(); i++) //输出 if(isdigit(a[i])) cout << a[i]; return 0; }
贪心策略:
每次从前往后找第一个连续递增序列的末尾,这样可以使删除末尾后的值是最小的。
举例:
135826 删除一个数
从前往后第一个连续递增序列为 1358 , 删除8, 得13526;
如果不删除8, 删除 5 或 2 , 分别得到 13826, 13586;都比13526要大。
因此贪心策略无误。(最好多找几个数据来测试贪心策略,我已经测试过了)
最后注意:
前导零不要忘了去除!
时间复杂度:O(t*n)
n为a的长度
我对贪心算法的理解
贪心算法是不从整体最优上加以考虑,它所做出的是在某种意义上的局部最优解。
确定题目用贪心算法时,首先确定贪心策略,选择一个看上去最好的方案。其次考虑局部最优解,把问题分成一个个小问题。最后
自然就得出了整个问题的最优解。