HDU 3183 A Magic Lamp

该题的题意是给你一个数字字符串,要你在其中抽去n个数字所组成的数字最小。

这个题可以从反方向出发,我们可以从中抽取字符串长度(len)减去n组成最小的数字;

我们知道要想最小第一个数前面一定没有比他大,也就是我们可以从0-(len-n-1)里面找最小的,找到之后,再从找到第一个数的位置后一个找第二个,以此类推。

再结合RMQ就可以了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<string.h>
using namespace std;
int dp[20][1024];
char num[1024],hash[1024];
int min( int i,int j )
{
return num[i]<=num[j]?i:j;
}
void RMQ( int n )
{
for( int i=0; i< n ;i++ )
{
dp[0][i]=i;
}
int t=( int )( log( double( n ) )/log( 2.0 ) );
for( int j=1; j<=t ; j++ )
{
for( int i=0; i+( 1<<j )-1<n; i++ )
{
dp[j][i]=min( dp[j-1][i],dp[j-1][i+( 1<<( j-1 ) )] );
}
}
}
int result( int left,int right )
{
int k=( int )( log( double( right-left+1 ) )/log( 2.0 ) );
return min( dp[k][left],dp[k][right-( 1<<k )+1] );
}
int main( )
{
int n;
while( scanf( "%s%d",num,&n )!=EOF )
{
int len=strlen( num );
RMQ( len );
int N=len-n;
int i=0,j=0;
while( N-- )
{
i=result( i,len-N-1 );
hash[j++]=num[i++];
}
for( i=0;i<j;i++ )
{
if( hash[i]!='0' )
break;
}
if( i==j ) printf( "0" );
else
{
while( i<j )
{
printf( "%c" , hash[i] );
i++;
}
}
puts( "" );
}
return 0;
}

 

你可能感兴趣的:(lamp)