ST算法:
题意是从一个n位数中删除m个数,使新得到的数最小(忽略前导零)
可以这样考虑,最后得到的是一个n-m位的数,那题意就可以理解为从一个n位数中按原次序挑选出n-m个数
那么第一位肯定要在[ 0,m ]之间产生,因为它后面还有n-m-1位数,假设第一位数的位置是x,那么同理,第二位要在[ x+1,m+1 ]上产生(这时候后面只剩下n-m-2位数了)
以此类推就可以找出这n-m个数了。
代码1:
#include <cstdio>
#include <cstring>using namespace std;
char num[1005],ans[1005];
int f[1005][1005];
int min(int a,int b)
{
return num[a]<=num[b]?a:b;
}
void init_RMQ(int len)
{
int i,k;
for(i=0;i<len;i++)
f[i][0]=i;
for(k=1;(1<<k)<=len;k++)
for(i=0;i+(1<<k)-1<len;i++)
f[i][k]=min(f[i][k-1],f[i+(1<<(k-1))][k-1]);
}
int RMQ(int a,int b)
{
int k=0;
while((1<<(k+1))<=b-a+1) k++;
return min(f[a][k],f[b-(1<<k)+1][k]);
}
int main()
{
int m,i;
while(scanf("%s%d",num,&m)!=-1)
{
int len=strlen(num);
init_RMQ(len);
m=len-m;
int i=0,j=0;
while(m--)
{
i=RMQ(i,len-m-1);
ans[j++]=num[i++];
}
for(i=0;i<j;i++)
if(ans[i]!='0') break;
if(i==j) printf("0");
else
for(;i<j;i++)
printf("%c",ans[i]);
printf("\n");
}
return 0;
}
代码2
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
char num[1005],ans[1005];
int f[1005][1005];
int min(int a,int b)
{
return num[a]<=num[b]?a:b;
}
void init_RMQ(int len)
{
int i,k;
for(i=0;i<len;i++)
f[i][0]=i;
for(k=1;(1<<k)<=len;k++)
for(i=0;i+(1<<k)-1<len;i++)
f[i][k]=min(f[i][k-1],f[i+(1<<(k-1))][k-1]);
}
int RMQ(int a,int b)
{
int k=0;
while((1<<(k+1))<=b-a+1) k++;
return min(f[a][k],f[b-(1<<k)+1][k]);
}
int main()
{
int m,i;
while(scanf("%s%d",num,&m)!=-1)
{
int len=strlen(num);
init_RMQ(len);
int i=0,j=0;
for(i=0;i<len-m;i++)
{
int a=RMQ(j,m+i);
ans[i]=num[a];
j=a+1;
}
for(i=0;i<len-m;i++)
if(ans[i]!='0') break;
if(i==len-m) printf("0");
else
for(;i<len-m;i++)
printf("%c",ans[i]);
printf("\n");
}
return 0;
}