貪心算法採用自頂向下,以迭代的方法做出相繼的貪心選擇,每做一次貪心選擇就將所求問題簡化爲一個規模更小的子問題,通過每一步貪心選擇,可得到問題的一個最優解,雖然每一步上都要保證能獲得局部最優解,但由此產生的全局解有時不一定是最優的,所以貪婪法不要回溯。能夠用貪心算法求解的問題一般具有兩個重要特性:貪心選擇性質和最優子結構性質。
參考:http://babybandf.blog.163.com/blog/static/61993532010112923767/
[例1]刪數問題[B][/B]
試題描述 鍵盤輸入一個高精度的正整數N(不超過240位),去掉其中任意S個數字後剩下的數字按左右次序組成一個新的正整數。對給定的N和S,尋找一種刪數規則使得剩下得數字組成的新數最小。
試題背景 此題出自NOI94[B][/B]
試題分析 這是一道運用貪心策略求解的典型問題。此題所需處理的數據從表面上看是一個整數。其實,大家通過對此題得深入分析便知:本題所給出的高精度正整數在具體做題時將它看作由若干個數字所組成的一串數,這是求解本題的一個重要突破。這樣便建立起了貪心策略的數學描述。
每次刪除一個數字,選擇一個使剩下的數最小的數字作爲刪除對象,之所以選擇這樣”貪心”的操作,是因爲刪S個數字的全局最優解包含了刪一個數字的子問題的最優解.
當S=1時,在N中刪除哪一個數字能達到最小的目的?從左到右每相鄰的兩個數字比較:若出現左邊大於右邊,則刪除左邊的大數字.若不出現降序排列,即所有數字全部升序,則刪除最右邊的大數字.
當S>1,按上述操作一個一個刪除,刪除一個達到最小後,再從頭即從串首開始,刪除第2個,依次分解爲S次完成.
若刪除不到S個後已無左邊大於右邊的減序,則停止刪除操作,打印剩下串的左邊L-S個數字即可(相當於刪除了若干個最右邊的大數字,這裏L爲原數字N的位數).
#include<iostream>
#include<string>
using namespace std;
int main()
{
string n;
int s,i,x,l,m;
while(cin>>n>>s)
{
i=-1,m=0,x=0;
l=n.length();
while(x<s&&m==0)
{
i++;
if(n[i]>n[i+1])//出現遞減,刪除遞減的首數字
{
n=n.erase(i,1);
x++;// x統計刪除數字的個數
i=-1;//從頭開始查遞減區間
}
if(i==l-x-2&&x<s)
m=1;//已經無遞減區間,m=1脫離循環
}
cout<<n.substr(0,l-s+x);//只打印剩下的左邊l-(s-x)個數字
}
}