A Magic Lamp HDU
阿新 • • 發佈:2018-12-19
題意
給定長度為n位的數字,刪去其中的m位數,不能改變數的順序,使剩下的數最小(如果剩下的數包含前導零輸出時則去掉)。
思路
此題是以所存最小數的位置(下標)進行預處理
最後輸出的是一個(n-m)位的數,輸出結果的第一位數最大的可選範圍為原數的 0~m(所存n位數的下標)位,一共進行 n-m 次選擇,每次選出最小的那個數的下標,最後一次選擇的右區間正好為 n-1 (0~n-1 一共n位)。假設第一次選出數的下標為 pos (0~m),則下一次從pos+1(pos+1~m+1)開始選則 。都為閉區間。
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; char s[1010],pre[1010]; int dp[1010][11]; int n,m; int minx(int x,int y) //返回的是最小數的下標 { return s[x]<=s[y]?x:y; } void 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]=minx(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } int query(int l,int r) { int k=(int)(log(r-l+1.0)/log(2.0)); return minx(dp[l][k],dp[r-(1<<k)+1][k]); } int main() { while(~scanf("%s%d",s,&m)) { n=strlen(s); rmq(); int pos=0; int i,j; for(i=0;i<n-m;i++) { pos=query(pos,m+i); pre[i]=s[pos++]; //將最小數存到pre[]中,並讓pos+1 } for(j=0;j<i;j++) //判斷前導零 if(pre[j]!='0') break; if(j==i) printf("0\n"); else { for(int k=j;k<i;k++) printf("%c",pre[k]); printf("\n"); } } return 0; }