COJ1236(删数游戏)

题目链接

经典贪心算法题。题目大意,给定一个整数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 }
原文地址:https://www.cnblogs.com/algorithms/p/2445309.html