python貪心演算法求刪數問題 演算法 貪心演算法

2021-10-18 15:51:53 字數 3514 閱讀 9478

概念&&介紹

貪心演算法是指,在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,演算法得到的是在某種意義上的區域性最優解。所以說只有證明區域性最優解在全域性最優解序列中,才能通過貪心演算法得到問題的全域性最優解。也就是說選擇的貪心策略必須具備無後效性,即某個狀態以後的過程不會影響以前的狀態,只與當前狀態有關。所以對所採用的貪心策略一定要仔細分析其是否滿足無後效性。

如圖0.0所示,我們從​點出發到達點​,如果我們想要在經過的路徑中累計數值最大,我們可以採取在每個分支處選擇數值最大的點的貪心策略。但顯然我們會選擇​的路徑,但實際上正解是路徑​,這是由於我們的選擇是具有後效性的,當前選擇的點會影響到後面可選擇的點,所以會導致我們不能得到全域性最優解。

如圖0.1所示,我們選擇三次,每次從兩點中選擇乙個點並累加它的數值,如果我們想要使累計的數值最大,我們可以選擇三次點​,並且我們最後得出的解是正解。這是由於我們的選擇不具有後效性,當前選擇的點並不會影響到後面可選擇的點,所以我們可以得到全域性最優解。

演算法流程把求解的問題分成若干個子問題。

對每一子問題求解,得到子問題的區域性最優解。

把子問題的解區域性最優解合成原來解問題的乙個解。

適用問題

區域性最優策略能導致產生全域性最優解。或者將貪心演算法進行修改以求出全域性最優解

深入理解&&例題

如果前面的兩個小例子不能使你透徹地理解貪心演算法,那麼我們可以來看看下面的幾個小例題,通過它們來深入理解貪心演算法以及貪心演算法使用的場景。

刪數問題

讀入乙個高精度整數​,去掉其中​個數字後剩下的數字按照原來的次序組成乙個新的正整數。尋求一種方案,使得最後組成的數最小。

分析題目,我們可以設計一種貪心策略:進行​輪刪數,每輪刪除最大的乙個數,如果數值相同則刪除靠前的乙個。

我們可以對這個貪心策略進行證明:每輪刪除的數字並不會影響後面可刪除的數字,因此這種貪心策略不具有後效性,且​次刪數後剩餘所有數字組成的數即為問題的可行解,因此這種貪心策略可行。

include

using namespace std;

int s,len;

char n[241];

int main()//找到目標數

for(int i=p+1;i

n[i-1]=n[i];

len--;//刪數

for(int i=0;i

cout<

return 0;

均分紙牌

如圖3.0所示,有​堆紙牌,編號分別為​。每堆上有若干張,但紙牌總數必為​的倍數。可以在任一堆上取若於張紙牌,然後移動。移牌規則:編號為​堆上取的紙牌,只能移到編號為​的堆上;編號為​的堆上取的紙牌,只能移到編號為​的堆上;其他堆上取的紙牌,可以移到相鄰左邊或右邊的堆上。現在要求找出一種移動方法,用最少的移動次數使每堆上紙牌數都一樣多。

分析題目,我們可以得知:要想使移動次數最少,就要把移動的浪費降到最低。例如在相鄰的兩堆間移動​次就是一種浪費,因為這​次移動都可以合併成​次。

因此,我們可以採用移動一次使得一堆牌數達到平均值的貪心策略:先把每堆的牌數減去平均數,然後由左而右的順序移動紙牌。若第​堆紙牌的張數​不為​,則將值移動到下一堆。如圖3.1所示,所有堆的紙牌平均數為​,我們可以先將每堆減掉平均數。

然後遍歷每堆紙牌,如圖3.2所示,紙牌數不為​則向下一堆移動,每次移動將移動次數​,最後得到圖3.3。

這種貪心策略類似於「把不足平均值的責任推給下一堆,直至多於平均值的紙牌堆來彌補」。通過求解兩個紙牌堆之間的最優子解,把所有子解合併得到問題的乙個可行解。

include

using namespace std;

int n,a[101],sum,ans;

int main(){

scanf("%d",&n);

for(int i=1;i<=n;i++){

scanf("%d",&a[i]);

sum+=a[i];

sum/=n;

for(int i=1;i<=n;i++){

a[i]-=sum;

for(int i=1;i<=n;i++){

if(a[i]!=0){

a[i+1]+=a[i];

ans++;

printf("%dn",ans);

return 0;

糖果傳遞

有​個小朋友坐成一圈,每人有​個糖果。每人只能給左右兩人傳遞糖果。每人每次傳遞乙個糖果代價為​。求使所有人獲得均等糖果的最小代價。

和均分紙牌類似,現在假設編號為​的人初始有​個糖果。對於​號來說,他給了​號​個糖果,還剩​個;但是因為​號給了他​個糖果,所以最後還剩​個糖果。根據題設,該金幣數等於​。換句話說,我們得到了乙個方程:​。

同理,對於第​個人,有​。最終,我們可以得到​個方程,一共​個變數,是不是可以直接解方程組了呢?很可惜,還不行。因為從前​個方程可以推導出最後乙個方程。所以,實際上只有​個方程是有用的。

儘管無法直接解出答案,我們還是可以嘗試著用​表示出其他的​,則本題就變成了單變數的極值問題。

對於第​個人,​(令​,下面類似) 對於第​個人,​(​) 對於第​個人,​ ......

對於第​個人,​。這是乙個多餘的等式,並不能給我們更多的資訊。我們希望所有的​的絕對值之和盡量小,即​要最小。注意到​的集合意思是數軸上點​到​的距離,所以問題變成了:給定數軸上的​個點,找出乙個到它們的距離之和盡量小的點。

結論:給定數軸上的​個點,在數軸上的所有點中,中位數離所有頂點的距離之和最小。凡是能轉化為這個模型的題目都可以用中位數求解。

include

define maxn 1000001

using namespace std;

int n,a[maxn];

long long c[maxn],sum,ans;

int main(){

scanf("%d",&n);

for(int i=1;i<=n;i++){

scanf("%d",&a[i]),sum+=a[i];

sum/=n;

for(int i=1;i<=n;i++){

c[i]+=sum-a[i]+c[i-1];

sort(c+1,c+n+1);

int mid=c[n/2];

for(int i=1;i<=n;i++){

ans+=abs(mid-c[i]);

printf("%lld",ans);

return 0;

高階習題洛谷 p1223 排隊接水 題目鏈結

洛谷 p1803 凌亂的yyy / 線段覆蓋 題目鏈結

洛谷 p3817 小a的糖果 題目鏈結

洛谷 p1478 陶陶摘蘋果(公升級版)題目鏈結

洛谷 p5019 鋪設道路 題目鏈結

洛谷 p1208 混合牛奶 題目鏈結

洛谷 p1094 紀念品分組 題目鏈結

洛谷 p1090 合併果子 題目鏈結

洛谷 p4447 分組 題目鏈結

洛谷 p1080 國王遊戲 題目鏈結

poj p3262 protecting the flowers 題目鏈結

poj p1716 integer intervals 題目鏈結

參考資料

python貪心演算法求刪數問題 貪心演算法 刪數問題

給定n位正整數a,去掉其中任意k n 個數字後,剩下的數字按原次序排列組成乙個新 的正整數。對於給定的n位正整數a和正整數 k,設計乙個演算法找出剩下數字組成的新數最 小的刪數方案。輸入格式 第 1 行是1 個正整數 a。第 2 行是正整數k。輸出格式 輸出最小數。輸入樣例 在這裡給出一組輸入。例如...

python貪心演算法求刪數問題 貪心演算法 刪數問題

給定n位正整數a,去掉其中任意k n 個數字後,剩下的數字按原次序排列組成乙個新的正整數。對於給定的n位正整數a 和正整數k,設計乙個演算法找出剩下數字組成的新數最小的刪數方案。演算法的原理應該是說從最高位開始,一次向低位搜尋,一旦遇到前一位 高位 的數大於當前位,則刪去前一位,直到刪除k個數,如果...

刪數問題 貪心演算法 Python

在給定的n個數字的數子串,刪除其中k k按照原次序組成乙個新的正整數。使得剩下的數字組成的新正整數最大。貪心思想,每次從左到右,刪除第乙個小於後者的元素,如果沒有,說明是已經降序排列,就從後面依次刪除。如果是要的是最小值則反之 time 2018 5 22 author yinxing def de...