经典贪心算法题。题目大意,给定一个整数N(位数最多2000)和整数k,在N中删除k个数使得剩下的数组成的整数最小。需要注意的是结果不要输出前导0。
贪心策略为:从高位到低位扫描,若存在递减区间,则将高位删除以消除递减区间,否则从低位删。具体操作时,可以设一个栈来保存从高位起还没删的数。不难发现最后的结果一定是一个不下降序列,由此可以想到用二分来优化。
View Code
1 #include <stdio.h> 2 #include <string.h> 3 #define MIN(a,b) ((a)<(b)?(a):(b)) 4 #define N 2005 5 char s[N]; 6 int d[N],top; 7 int main() 8 { 9 int i,j,k,len,cnt,f; 10 int t,min,max,mid; 11 while(~scanf("%s%d",&s[1],&k)) 12 { 13 s[0]=-1,top=0; 14 d[top++]=0; 15 len=strlen(s); 16 for(i=1,cnt=0;cnt<k&&i<=len;) 17 { 18 if(top==1||s[i]>=s[d[top-1]]) 19 { 20 d[top++]=i++; 21 continue; 22 } 23 else 24 { 25 min=0,max=top-1; 26 while(min+1!=max) 27 { 28 mid=(min+max)>>1; 29 if(s[i]<s[d[min]]) max=mid; 30 else min=mid; 31 } 32 t=MIN(k-cnt,top-max); 33 top-=t,cnt+=t; 34 } 35 } 36 f=1; 37 for(j=1;j<top&&s[d[j]]=='0';j++); 38 for(;j<top;j++) printf("%c",s[d[j]]),f=0; 39 if(f) for(;i<len&&s[i]=='0';i++); 40 for(;i<len;i++) printf("%c",s[i]),f=0; 41 if(f) printf("0"); 42 printf("\n"); 43 } 44 return 0; 45 }