1. 程式人生 > 實用技巧 >基礎演算法:貪心(待整理)

基礎演算法:貪心(待整理)

貪心演算法的定義與性質:

  • 貪心演算法是通過做出一系列 選擇 來求出問題的最優解。在每一個決策點,它作出在 當前看來最好 的選擇。

    • (也就是說貪心演算法並 不從整體最優上加以考慮 ,它所作出的選擇只是在某種意義上的 區域性最優選擇 。大概也是貪心演算法名字的由來)

    • (貪心演算法進行決策時, 可能依賴於以往所做出的選擇,但決不依賴於將來所做的選擇,或者子問題的解 。)

  • 貪心演算法必須滿足 最優子結構 。與動態規劃不同,貪心的最優子結構,必須滿足 選擇後只留下一個子問題

    • (從最優子結構的角度說:相當於特殊的動態規劃。動態規劃的選擇後往往會產生多個子問題。)

    • (正是由於這種差異,動態規劃演算法通常以自底向上的方式解各子問題,而 貪心演算法則通過以自項向下的方式

      進行,以 迭代 的方式做出相繼的貪心選擇,每做一次貪心選擇就將所求問題簡化為規模更小的子問題 。)

  • 貪心的正確性:必須滿足 貪心選擇剩餘相容活動集 的最優解,組合在一起後,就會得到原問題的最優解。

PS:可以設計一個遞迴演算法實現貪心策略,再將遞迴演算法轉化為迭代演算法。因為迭代的效率更高。
PS:若在進行貪心選擇中,不得不考慮列舉眾多選擇來找到最優,通常意味著可以改進貪心選擇,使其更高效。通常的改進辦法是:使用 合適的資料結構預處理

打水問題:

刪數問題:

#include<bits/stdc++.h>
#define MAXN 10000
using namespace std;
int main()
{
	string s;	int len,k;
	cin>>s>>k;	len=s.size();
	for(int t=1;t<=k;++t)
	{
		for(int i=0;i<len;++i)
		{
			if(s[i]>s[i+1])
			{
				for(int j=i;j<len;++j)
					s[j]=s[j+1];
				--len;
				break;
			}
		}
	}
	int i;	for(i=0; s[i]=='0' ;++i);
	if(i==len) cout<<"0";
	else
	{
		for(;i<len;++i)
			cout<<s[i];
	}
	return 0;
}

僱傭計劃:

#include <bits/stdc++.h>
using namespace std;
int ned[100]; 
int main()
{
    int n,a,b,c,more;
	int choice1,choice2,k;
    scanf("%d%d%d%d",&n,&a,&b,&c);
    for(int i=1;i<=n;++i) scanf("%d",&ned[i]);
    int ans=(a+b)*ned[1];
    for (int i=2;i<=n;++i)
    {
        ans+=b*ned[i],more=ned[i]-ned[i-1];
        if(more>=0) ans+=a*more;
        else
        {
        	more=abs(more);
            for (int j=1;j<=more;++j)
            {
                choice1=0;
                for (k=i+1;k<=n;++k)
                    if (ned[k]>ned[i]) {choice1=a;break;}	choice1+=c;//dismiss
                choice2=b*(k-i);//employ
                if (choice1>=choice2) ++ned[i],ans+=b;
                else {ans+=c*(more-j+1);break;}
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

拔河:

三國遊戲: