题目
描述
给定一个十进制正整数n(0 < n < 1000000000),每个数位上数字均不为0。n的位数为m。
现在从m位中删除k位(0<k < m),求生成的新整数最小为多少?
例如: n = 9128456, k = 2, 则生成的新整数最小为12456
输入
第一行t, 表示有t组数据;
接下来t行,每一行表示一组测试数据,每组测试数据包含两个数字n, k。
输出
t行,每行一个数字,表示从n中删除k位后得到的最小整数。
样例输入
2
9128456 2
1444 3
样例输出
12456
1
一、分析
9128456去除两个数后是最大数
先删9,结果128456是最大数。(每步都是最佳值)。发现:从左开始比下一个数大的可以删
再删8
1444 3
先删第一个4,再4,再4,都是删一个后的最大数。发现:相等后没有小的,就可以删。
自己数据444921 3
44421
4421
421
发现是要删9比2大,但是不能继续往后删2比1大,而是从头开始。
二、归纳
1.删第一个比下一个大的数,但是不能继续,下次从头开始
2.如果跟下一个数一样,找第一个不一样的
如果比下一个数大,删除自己
如果比下一个数下,没有动作,转换成1的问题
如果没有不一样的,删除自己
三、总结
贪心算法每一步都在算结果。动态规划每一步都在算状态,这个状态不一定是最后结果。
四、数据结构
容器,
clear清空
push_back()在队列后添加数据
pop_back()清除队列后数据
size()队列长度
用指针遍历元素vector::iterator x=v.begin();x!=v.end();x++
x.erase(x)清空该元素
五.代码
#include <bits/stdc++.h>
using namespace std;
int t,m;
string s;
vector v;
template //模板类型参数,通用不同类型参数
void view(mo s){
//cout<<s<<“:”;
for(int i=0;i<v.size();i++)cout<<v[i]; cout<<endl;
}
int main(){
//freopen(“in.cpp”,“r”,stdin);
cin>>t;
while(t–){
cin>>s>>m;
//cout<<s<<“\t”<<m<<endl;
v.clear();
for(int i=0;i<s.length();i++)v.push_back(s[i]-‘0’);
//循环一次只删除一个数字
while(m){
int m2=m;
for(vector::iterator i=v.begin();i!=v.end()&&(i+1)!=v.end();i++){
if(i>(i+1)){
v.erase(i);m–;break;//删除大于下一个数字的数字,下次得从头开始
//如,567132,删完7后,不能删3,因为6大于1。
}else if(i==(i+1)){//相等的话,不需要从头找
vector::iterator j=i;j++;
while(j!=v.end()&&*j==*i)j++;//找到后面不一样的数
if(jv.end()){v.erase(i);m–;}//到尾,就删除自己
else if(*i>*j){v.erase(i);m–;}//大了也删自己
else if(*i*j){v.erase(i);m–;}//一样了也删自己。
}
}
if(m==m2)break;//删不了就不再循环
//view(m);
}
//上述完了后,只剩升序序列,可以从后删除
while(m){v.pop_back();m–;}
view(“结果”);
}
return 0;
}
经验总结
仔细分析问题,观察数据变化,整理归纳规律。一个平静且谦虚的心态很重要。