目錄
題目描述
鍵盤輸入一個高精度的正整數NN(不超過250250位) ,去掉其中任意kk個數字後剩下的數字按原左右次序將組成一個新的正整數。編程對給定的NN和kk,尋找一種方案使得剩下的數字組成的新數最小。
輸入格式
nn (高精度的正整數)
kk(需要刪除的數字個數)
輸出格式
最後剩下的最小數。
輸入輸出樣例
輸入 #1複製
175438
4
輸出 #1複製
13
分析:
- 首先:要讓剩餘的數最小,由於刪的個數是確定的,即剩餘的個數是確定的。當高位數字越小時,得到剩餘的數字就越小。如此便得到此題的關鍵。
- 若要從長度爲len的數中,刪掉m個數字。首先如何確定要保留的最高位數字?
如果從34125中刪掉2個數,顯然最高位是1
如果從31245中刪掉2個數,顯然最高位仍然是1
如果從34215中刪掉2個數,最高位最小隻能是2
由此得到結論:第一位數字要從前m+1個數中選擇一個最小的,前面的刪掉。
- 同樣的,第二位數字的選擇和第一位是一樣的道理。如果此時m已經用完,直接把後面的數拼接到結果數組中即可。否則仍按照上述規則尋找。
- 如果僅想到上面這些,並不能AC。原因是0的存在。。。。。。。
舉個栗子:
從50074897中刪除2個。答案是4897.
如果仍然按上述規則寫,答案卻是004897,此時,只需要考慮保存答案數組時,特判一下是否是0即可。
- 最後,把上面的全做完了,但。。。。。仍然不能AC。。。。。。。TMD!!!
再舉個梨子,從10000中刪除兩個數。答案是0。按照上述規則來寫,最後沒有輸出,因此,特判一下結果數組的長度,如果最後結果數組的長度是0,直接輸出0.
代碼如下:
#include <bits/stdc++.h>
using namespace std;
const int MAX = 255;
char str[MAX],res[MAX];
int N;
int main() {
gets(str);
scanf("%d",&N);
int x = 0;
while (str[x]=='0') x++; //清空一下給出數字的前導0
if(x) strcpy(str,str+x);
int countRes=0,cut=0;
for(int i=0; i+N+1 < strlen(str); i++) {
if(N==0) {
strcpy(res+countRes,str+i); //已經刪完,把後面的數拼接過來即可
break;
}
int bk=i;
for (int j = 0; j < N; ++j) {
if(str[i+1+j]<str[bk]) {
bk=j+1+i;
}
}
N-=bk-i; //此次需要刪除多少個,刷新一下N
if(str[bk]!='0'){
res[countRes++]=str[bk]; //特判,如果不是0才能添加到結果數組中
}
i=bk; //恢復i的索引。
}
if(countRes) puts(res);
else puts("0");
}