题目描述
11月15号是GG的破蛋日,这一天萌萌的GG很早就起床,小(zi)小(xi)打扮了一下,就去参加传说中的ACM-ICPC亚洲赛了。 这一去让原本萌萌哒的GG变得更加萌 了,在那凶残的北京赛区中GG被虐的萌萌哒连回家的路都忘记了。于是萌萌的GG便向英勇帅气的DX问起路来,但是DX不想让GG这么容易就能回家,于是他出了一道ACM题,说只要GG能够做出来,就带他回家。 呜呜~~~~(>_<)~~~~ ,这可难倒GG,于是GG哭着向聪明的你请教,希望你能做出来,不然GG就回不了家了。。。 题目是这样紫滴:
输入
数据有T组,给你两个值s,k ( 1 <=T <= 10000,2 <= strlen(s) <= 1000, 0 <= k < strlen(s)); s表示一个字符串(只包含数字,没有前导0),k表示在这个s中删除k个数,使最后得到数(没有前导0)最小。
输出
对于每一组数据输出“Case #x: y”,x表示第几组,y表示删除后得到的最小的数,注意双引号不要输出。
样例输入
样例输出
提示
第一组数据删除9和6得到数最小; 第二组删除1,比删除其他数,得到的值小;
来源
分析:
1、明天就要蓝桥杯比赛了,今天就猛刷题。读完这道题后,看见输入数字位数会达到1000位,就会想到数组处理,然后会想到不是常规做法,就寻找其中的计算方式。
2、好久没有做过贪心题了,这是一道贪心题。当我们拿到一个数后,输出最小,肯定是从最高开始判断,删除后位数肯定小于等于strlen(s)-k,所以,从最高位开始遍历,寻找相对于下一位大的数字,然后删除。如91623,9比1大,所以删除9,然后遍历,1比6小,不删除,继续遍历,接着6比2大,所以删除6。到此,已经删除2位数字了,结束遍历。用这种方法解决,复杂度是相当低的,10以内就10个数,必删除一个。若是个递增数列,就删除后面数字呗。
3、程序需要处理一下细节,我为了ac它,就没把程序简化了。首先要考虑到当一样大的时候,还要回去删除数字,如9996623,删除2个数字吧,比到9比6时,删除9,然后需要判断前面是否有9。另外就是输出时,注意没有前导0.
LANGUAGE :C++
CODE:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int t,cnt;
char arr[1005];
cin>>t;
int count=0;
while(t--)
{
cin>>arr;
cin>>cnt;
//cout<<arr[0]<<endl;
int m=0;
int ans=0; //删除相同数字,移位时不再从0开始了
for(int i=0;cnt&&i<strlen(arr)-1;i++){
if(arr[i]>arr[i+1]){
//cout<<arr[i]<<endl;
bool flaggg;
do{
flaggg=false;
for(int j=i;j>ans;j--){
arr[j]=arr[j-1];
flaggg=true; //判断前面是否有没有删除的数字
}
cnt--;
m++; //记录删除多少数字后,输出时的起点位置
ans++;
//cout<<cnt<<endl;
}while(arr[i]>arr[i+1]&&cnt&&flaggg); //判断前面是否有相同的数字
}
}
bool flag=true;
bool fla=true;
count++;
cout<<"Case #"<<count<<": ";
//cout<<m<<endl;
for(int i=m;i<strlen(arr)-cnt;i++)
{
if(arr[i]!='0'&&flag) //前导是0时不输出
{
cout<<arr[i];
flag=false;
fla=false;
}
else if(!flag) //不是前导0或其他数输出
cout<<arr[i];
}
if(flag&&fla) //如果剩余的全是0时,输出结果0
cout<<0;
cout<<endl;
}
}