zoukankan      html  css  js  c++  java
  • HDU 3183 A Magic Lamp (双向链表贪心删除 或者是 RMQ取数)

    A Magic Lamp

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 745    Accepted Submission(s): 271


    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 1 100001 2 12345 2 54321 2
     
    Sample Output
    13 1 0 123 321
     
    Source
     
    Recommend
    lcy
     
     
    方法一是我自己想出来的。就是每次删除数的时候都是删掉第一个比右边数大的数。
    比如样例 178543  4
    第一次删除第一个数的时候从左边找起。找到第一个a[i]>a[i+1]的数。删除8
    17543
    第二次一样的,删除7
    1543
    第三次删除5
    143
    第四次删除4
    就得到13了。就是答案。
     
    用双向链表,可以很方便的删除,速度也很快。
    /*
    HDU 3183
    G++  0ms
    双向链表,每次删除掉第一个比右边的数大的数
    */
    
    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int MAXN=1010;
    struct Node
    {
        int from,to;
        int v;
    }node[MAXN];
    int tol;
    void del(int t)//删除t结点
    {
        int temp=node[t].from;
        node[temp].to=node[t].to;
        node[node[t].to].from=temp;
    }
    char str[MAXN];
    int main()
    {
        //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        int m;
        while(scanf("%s%d",&str,&m)!=EOF)
        {
            int n=strlen(str);
            for(int i=1;i<=n;i++)
            {
                node[i].v=str[i-1]-'0';
                node[i].from=i-1;
                node[i].to=i+1;
            }
            node[0].to=1;
            node[n+1].from=n;
            int t=0;
            while(m--)
            {
                while(node[t].to!=n+1 && node[node[t].to].v>=node[t].v) t=node[t].to;
                del(t);
                t=node[t].from;
            }
            t=node[0].to;
            while(t!=n+1 && node[t].v==0)t=node[t].to;
            if(t==n+1)
            {
                printf("0\n");
                continue;
            }
            while(t!=n+1)
            {
                printf("%d",node[t].v);
                t=node[t].to;
            }
            printf("\n");
        }
        return 0;
    }

    第二种方法就是反过来考虑,取n-m个数,使得形成的数最小。

    RMQ。

    /*
    HDU 3183
    */
    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<math.h>
    #include<string.h>
    using namespace std;
    const int MAXN=1010;
    int a[MAXN];
    int dp[MAXN][20];
    
    void makeRMQIndex(int n,int b[])//形成最小值下标的RMQ
    {
        for(int i=0;i<n;i++)
          dp[i][0]=i;
        for(int j=1;(1<<j)<=n;j++)
           for(int i=0;i+(1<<j)-1<n;i++)
              dp[i][j]=b[dp[i][j-1]]<=b[dp[i+(1<<(j-1))][j-1]]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1];
              //这里一定要加等号,就是相等的时候取下标小的
    }
    int rmqIndex(int s,int v,int b[])
    {
        int k=(int)(log(v-s+1.0)/log(2.0));
        return b[dp[s][k]]<=b[dp[v-(1<<k)+1][k]]?dp[s][k]:dp[v-(1<<k)+1][k];
        //加等号,取小标小的
    }
    char str[MAXN];
    int ans[MAXN];
    int main()
    {
        //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        int m;
        while(scanf("%s%d",&str,&m)!=EOF)
        {
            int n=strlen(str);
            for(int i=0;i<n;i++)a[i]=str[i]-'0';
            makeRMQIndex(n,a);
            int t=0;
            int temp=0;
            for(int i=m;i<n;i++)//找n-m个数,每次从[t,i]中找最小的
            {
                t=rmqIndex(t,i,a);
                ans[temp++]=a[t++];
            }
            t=0;
            while(t<temp&&ans[t]==0)t++;
            if(t>=temp)printf("0\n");
            else
            {
                for(int i=t;i<temp;i++)printf("%d",ans[i]);
                printf("\n");
            }
        }
        return 0;
    }
  • 相关阅读:
    Extjs4 MVC Controller中refs使用
    Mac下下载android4.2源码,进行源码调试
    来博客园一年三个月
    今天写的比较多
    Extjs4 MVC 添加view层
    mac自带vim7配置
    动态测试及调试工具
    等价类划分的延伸
    用javascript进行测试用例的验证
    同行评审在软件测试中的应用
  • 原文地址:https://www.cnblogs.com/kuangbin/p/2696721.html
Copyright © 2011-2022 走看看