刪數問題-貪心

題目:html

鍵盤輸入一個高精度的正整數N(不超過250位) ,去掉其中任意k個數字後剩下的數字按原左右次序將組成一個新的正整數。ios

編程對給定的Nk,尋找一種方案使得剩下的數字組成的新數最小。算法

 

算法思路:編程

要從正整數中刪除k個數字,能夠採起一步步來刪的策略,每一次刪除一個數字,使得當前獲得的數字是最小的,執行k步後,即獲得最後的結果。函數

經過子問題的最優解來獲得整個問題的最優解,就是貪心的思想。spa

例如:7122145這個數字,若是k=3,第一次刪除的應該是7,獲得122145;第二次刪除的應該是5,獲得12214;第三次刪除的應該是4,獲得1221.code

 

經過觀察,能夠發現每次刪除的數字有這樣的規律:htm

都是整個數字中遞減區間的第一個數字,若是整個數中沒有遞減區間,就刪除最後一個數字,由於要想留下的數字最小,它的高位確定要儘量小,blog

這樣刪除的方法,在當前次看來都是最優的,咱們把降序區間的第一個數刪掉,就能夠讓後面比他小的數前進一個高位,那麼數字也就變小了,ci

若是咱們刪除了這個最優數字前面的數,那麼這個比較大的數字就前進了一個高位,反而讓數字變大了,

一樣的,若是咱們刪除這個數後面的也很大的數字,雖然能讓小的數也前進一個高位,可是它自己處的位置也很低,顯然沒有讓利益最大化。

 

上代碼:

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;  4 int main() {  5     string n;  6     int k;  7     cin >> n;  8     cin >> k;  9     while (k != 0) { 10         int flag = 0; 11         for (int i = 0; i < n.length()-1; i++) { 12             if (n[i] > n[i + 1]) { 13                 n.erase(i, 1); 14                 flag = 1; 15                 break; 16  } 17  } 18         //若是數字都是單調遞增的,就刪除最後一個
19         if(!flag) n.erase(n.length() - 1, 1); 20         k--; 21  } 22     int i = 0; 23     if (n == "0") { 24         cout << n; 25         return 0; 26  } 27     //將首位的0去掉
28     while (n[i] == '0') { 29         i++; 30  } 31     for (int j = i; j < n.length(); j++) { 32         cout << n[j]; 33  } 34 
35     return 0; 36 }

 

其中,string中的erase()函數的用法在個人另外一篇博客中有總結。

相關文章
相關標籤/搜索