HDU 3183

来源:互联网 发布:锦绣未央网络首播量 编辑:程序博客网 时间:2024/05/17 08:26

      这道题的解法有多种,一种是用解决RMQ问题的ST算法,个人感觉比较难想到,另一种是较为朴素的方法。

      首先,说一下第一种方法。求数字的前m+1个数字中最小的那个,最小数字前的数字都是要删除的数字,假设此时还可以删数字个数为p,在从选中的最小数字的后面开始,求p+1个数字中最小的那个,如此循环,直到不能再删数字时停止。

     然后,说一下第二种方法。首先要知道一点,如果对一个数,只删除一个数字,使改变后的数成为最小的数字,那么我们应该从头开始找一个连续的非递减数字序列,把这个序列中的最后一个数删除,就可以得到这个要求的数了。这一点,想一想应该就明白了。所以,要删除m个数字,便可以按这个思路去做。

     最后,谈一下自己对两种方法的一点感想。第一种方法,是选出len-m个数字组成最小数字,第二种,是删除m个数字,选出最小数字。而且,第一种方法,必须先知道要删多少个数字,第二种,则不必。

     代码(G++):

方法一:

#include <cstdlib>#include <iostream>#include <cmath>#define MAX 1003//#define LOCALusing namespace std;int dp[MAX][MAX];char s[MAX];int min(int a,int b)    //返回最小数字对应的下标 {    return s[a]<=s[b]?a:b;}void st(int n){     int i,j;     for(i=0;i<n;i++) dp[i][0]=i;     for(i=1;(1<<i)<=n;i++)      //区间长度      {        for(j=0;j+(1<<i)<=n;j++)      //区间起点         {           dp[j][i]=min(dp[j][i-1],dp[j+(1<<(i-1))][i-1]);                     }                  }}int query(int a,int b)   //查询                                            {    int k;    k=log(b-a+1)/log(2);        return min(dp[a][k],dp[b-(1<<k)+1][k]);}int main(int argc, char *argv[]){#ifdef LOCAL   freopen("in.txt","r",stdin);   freopen("out.txt","w",stdout);#endif    int m,len,i,c;    char ans[MAX];         while(scanf("%s %d",s,&m)!=EOF)    {        len=strlen(s);        st(len);        c=i=0;           while(m<len)        {            i=query(i,m);            ans[c++]=s[i++];            m++;                 }        ans[c]='\0';                      i=0;        while(i<c)        {           if(ans[i]=='0') i++;           else break;                 }        if(i==c) printf("0\n");        else printf("%s\n",ans+i);              }     system("PAUSE");    return EXIT_SUCCESS;}

第二种:

#include <cstdlib>#include <iostream>#define MAX 1003//#define LOCALusing namespace std;int main(int argc, char *argv[]){#ifdef LOCAL   freopen("in.txt","r",stdin);   freopen("out.txt","w",stdout);#endif    int m,len,i,c;    char ans[MAX],s[MAX];         while(scanf("%s %d",s,&m)!=EOF)    {        len=strlen(s);        c=0;        ans[c++]=s[0];        for(i=1;i<len;i++)        {            if(c-1<0||ans[c-1]<=s[i]||m==0) ans[c++]=s[i];                  else{               while(m>0&&c>0&&ans[c-1]>s[i])               {                  c--;                   m--;               }               ans[c++]=s[i];            }                }                 if(m>0) c-=m;         ans[c]='\0';        i=0;        while(i<c)        {            if(ans[i]=='0') i++;            else break;              }          if(i==c) printf("0\n");        else printf("%s\n",ans+i);                 }     system("PAUSE");    return EXIT_SUCCESS;}

题目(http://acm.hdu.edu.cn/showproblem.php?pid=3183):

A Magic Lamp

                                                                         Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)


Problem Description
Kiki likes traveling. One day she finds a magic lamp, unfortunately the genie in the lamp is not so kind. Kiki must answer a question, and then the genie will realize one of her dreams. 
The question is: give you an integer, you are allowed to delete exactly m digits. The left digits will form a new integer. You should make it minimum.
You are not allowed to change the order of the digits. Now can you help Kiki to realize her dream?
 

Input
There are several test cases.
Each test case will contain an integer you are given (which may at most contains 1000 digits.) and the integer m (if the integer contains n digits, m will not bigger then n). The given integer will not contain leading zero.
 

Output
For each case, output the minimum result you can get in one line.
If the result contains leading zero, ignore it. 
 

Sample Input
178543 4 1000001 1100001 212345 254321 2
 

Sample Output
1310123321

0 0
原创粉丝点击