zoukankan      html  css  js  c++  java
  • hdu-3183A Magic Lamp(贪心)

    题目的意思是:

    给你一个大数,然后删减其中的K个数,并且剩下的数还是按原来在的先后次序排列,求所得的那个数最小的那个数。

    思路:贪心(要取得数最小,你从左往右选数的时候,选的第一数,就是选后组成数的位权最高的,要一个数最小,位权最高的所对应那位要最小,然后依次是下一位权最小)。原来有N个数,删除K个数得最小数可以转化为从左往右选N-K个数所组成的数最小。那么第一个数必须在区间[0,K](数组下标)(存大数的数组首位是从0开始的)。

    证:选的第一位数如果超过K,假如取的是K+S(K+S<=N-1)那么从(K+S+1)到N-1还剩下(N-K-S-1)个数,因为已经选了一个数剩余(N-K-1)个数没选,那么这些数必定要在区间

    [K-S+1,N]上选。又(N-K-1)大于区间长度N-K-S-1(S>=1).

    所以第一个数只能在[0,K]上取,且要取最小值,每位取当前区间最小才能保证最后所得数最小。

    那么当第一个数取完后,取的是pos位置的,那么在[0,pos-1]是未取得数,也就是去掉的数,因为后面省下的(N-K-1)个数不能在这些位置去,因为这些数在pos之前,所以如果去的话

    在所得的数中位置在第一个数之前,所以与pos为第一个数矛盾。

    这样你选第二个数时此时K应该更新为K-(pos+1-n)(n为当前所选好的数的个数(当前n=1)),pos更新为pos+1;那么第二个数在区间[pos,pos+K]其实pos+K就为K+n;

    那么这样直到选好N-K个数就行了。

     /*RMQ优化 复杂度为n*log(n)*/
    1
    #include<stdio.h> 2 #include<algorithm> 3 #include<iostream> 4 #include<stdlib.h> 5 #include<string.h> 6 #include<math.h> 7 void RMQup(int k,int l); 8 int que(int i,int j); 9 int Min(int x,int y); 10 char a[2000]; 11 int b[2000]; 12 const int N=100; 13 int RMQ[1005][1005]; 14 using namespace std; 15 int main(void) 16 { 17 int n,i,j,k,p,q,l,m; 18 while(scanf("%s",a)!=EOF) 19 { 20 scanf("%d",&k); 21 l=strlen(a); 22 p=l-k; 23 for(i=0; i<l; i++) 24 RMQ[0][i]=i; 25 int r=log2(l); 26 r++; 27 RMQup(r,l); 28 int pp,qq; 29 int dd; 30 pp=0; 31 m=k; 32 int coutt =0; 33 while(coutt<p)//选好p个数字就结束 34 { 35 int z=que(pp,m); 36 b[coutt++]=a[z]-'0'; 37 pp=z+1; 38 m++; 39 } 40 for(i=0; i<p; i++) 41 { 42 if(b[i]!=0) 43 { 44 break; 45 } 46 } 47 for(j=i; j<p; j++) 48 { 49 printf("%d",b[j]); 50 } 51 if(i==p) 52 { 53 printf("0"); 54 } 55 printf(" "); 56 } 57 58 return 0; 59 60 61 } 62 63 64 void RMQup(int k,int l)//dp求RMQ(这种RMQ链接讲解http://www.cnblogs.com/zzuli2sjy/p/4971449.html 65 { 66 int i,j; 67 for(i=1; i<=k; i++) 68 for(j=0; j<l; j++) 69 if(j+(1<<i-1)<l) 70 RMQ[i][j]=Min(RMQ[i-1][j],RMQ[i-1][j+(1<<i-1)]); 71 72 } 73 74 int que(int i,int j) 75 { 76 int f=log2(j-i+1); 77 return Min(RMQ[f][i],RMQ[f][j-(1<<f)+1]); 78 79 } 80 int Min(int x,int y)//求在某段的最小值的数组下标 81 { 82 if(a[x]==a[y]) 83 { 84 return x<y?x:y;//当两个数相同时返回数组下标小的(比如223 要去1个数字,答案是22,如果返回数组下标大的结果就是23了) 85 } 86 else 87 { 88 return a[x]<a[y]?x:y; 89 } 90 }
     1 /*直接循环找段最小*/
     2 #include<stdio.h>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<stdlib.h>
     6 #include<string.h>
     7 using namespace std;
     8 char a[1005];
     9 char b[1005];
    10 int main(void)
    11 {
    12     int n,i,j,k,p,q,l;
    13     while(scanf("%s",a)!=EOF)
    14     {
    15         scanf("%d",&k);
    16         l=strlen(a);
    17         if(k==l)
    18         {
    19             printf("0
    ");
    20         }
    21         else
    22         {
    23             int y=l-k;
    24             int x=0;
    25             int m=y;
    26             int coutt=0;
    27             int dd;
    28             dd=0;
    29             while(coutt<y)
    30             {
    31                 b[coutt]=a[x];
    32                 for(i=x; i<=x+k; i++)//循环找最小
    33                 {
    34                     if(a[i]<b[coutt])
    35                     {
    36                         b[coutt]=a[i];
    37                         dd=i;
    38                     }
    39 
    40                 }
    41                 dd=dd+1;
    42                 k-=(dd-x-1);
    43                 coutt++;
    44                 x=dd;
    45             }
    46             for(i=0; i<coutt; i++)
    47             {
    48                 if(b[i]!='0')
    49                 {
    50                     break;
    51                 }
    52             }
    53             if(i==coutt)
    54             {
    55                 printf("0");
    56             }
    57             for(j=i; j<coutt; j++)
    58             {
    59                 printf("%c",b[j]);
    60             }
    61             printf("
    ");
    62         }
    63     }
    64     return 0;
    65 }
    油!油!you@
  • 相关阅读:
    Leetcode 1489找到最小生成树李关键边和伪关键边
    Leetcode 113 路径总和 II
    hdu 1223 还是畅通工程
    hdu 1087 Super Jumping! Jumping! Jumping!
    hdu 1008 Elevator
    hdu 1037 Keep on Truckin'
    湖工oj 1241 畅通工程
    湖工oj 1162 大武汉局域网
    hdu 2057 A + B Again
    poj 2236 Wireless Network
  • 原文地址:https://www.cnblogs.com/zzuli2sjy/p/4972032.html
Copyright © 2011-2022 走看看