當前位置:首頁 » 操作系統 » 貪心演算法單

貪心演算法單

發布時間: 2022-06-25 10:24:32

① 貪心演算法的例題分析

例題1、
[0-1背包問題]有一個背包,背包容量是M=150。有7個物品,物品不可以分割成任意大小。
要求盡可能讓裝入背包中的物品總價值最大,但不能超過總容量。
物品 A B C D E F G
重量 35kg 30kg 6kg 50kg 40kg 10kg 25kg
價值 10$ 40$ 30$ 50$ 35$ 40$ 30$
分析:
目標函數:∑pi最大
約束條件是裝入的物品總重量不超過背包容量:∑wi<=M(M=150)
⑴根據貪心的策略,每次挑選價值最大的物品裝入背包,得到的結果是否最優?
⑵每次挑選所佔重量最小的物品裝入是否能得到最優解?
⑶每次選取單位重量價值最大的物品,成為解本題的策略。
值得注意的是,貪心演算法並不是完全不可以使用,貪心策略一旦經過證明成立後,它就是一種高效的演算法。
貪心演算法還是很常見的演算法之一,這是由於它簡單易行,構造貪心策略不是很困難。
可惜的是,它需要證明後才能真正運用到題目的演算法中。
一般來說,貪心演算法的證明圍繞著:整個問題的最優解一定由在貪心策略中存在的子問題的最優解得來的。
對於例題中的3種貪心策略,都是無法成立(無法被證明)的,解釋如下:
⑴貪心策略:選取價值最大者。
反例:
W=30
物品:A B C
重量:28 12 12
價值:30 20 20
根據策略,首先選取物品A,接下來就無法再選取了,可是,選取B、C則更好。
⑵貪心策略:選取重量最小。它的反例與第一種策略的反例差不多。
⑶貪心策略:選取單位重量價值最大的物品。
反例:
W=30
物品:A B C
重量:28 20 10
價值:28 20 10
根據策略,三種物品單位重量價值一樣,程序無法依據現有策略作出判斷,如果選擇A,則答案錯誤。
【注意:如果物品可以分割為任意大小,那麼策略3可得最優解】
對於選取單位重量價值最大的物品這個策略,可以再加一條優化的規則:對於單位重量價值一樣的,則優先選擇重量小的!這樣,上面的反例就解決了。
但是,如果題目是如下所示,這個策略就也不行了。
W=40
物品:A B C
重量:25 20 15
價值:25 20 15
附:本題是個DP問題,用貪心法並不一定可以求得最優解,以後了解了動態規劃演算法後本題就有了新的解法。
例題2、
馬踏棋盤的貪心演算法
123041-23 XX
【問題描述】
馬的遍歷問題。在8×8方格的棋盤上,從任意指定方格出發,為馬尋找一條走遍棋盤每一格並且只經過一次的一條路徑。
【初步設計】
首先這是一個搜索問題,運用深度優先搜索進行求解。演算法如下:
⒈ 輸入初始位置坐標x,y;
⒉ 步驟 c:
如果c> 64輸出一個解,返回上一步驟c--
(x,y) ← c
計算(x,y)的八個方位的子結點,選出那些可行的子結點
循環遍歷所有可行子結點,步驟c++重復2
顯然⑵是一個遞歸調用的過程,大致如下:
C++程序: #defineN8voiddfs(intx,inty,intcount){inti,tx,ty;if(count>N*N){output_solution();//輸出一個解return;}for(i=0;i<8;i++){tx=hn[i].x;//hn[]保存八個方位子結點ty=hn[i].y;s[tx][ty]=count;dfs(tx,ty,count+1);//遞歸調用s[tx][ty]=0;}}Pascal程序: ProgramYS;ConstFXx:array[1..8]of-2..2=(1,2,2,1,-1,-2,-2,-1);FXy:array[1..8]of-2..2=(2,1,-1,-2,-2,-1,1,2);VarRoad:array[1..10,1..10]ofinteger;x,y,x1,y1,total:integer;ProcereFind(x,y:integer);varNx,Ny,i:integer;BeginFori:=1to8dobegin{8個方向}If(x+FXx[i]in[1..8])and(y+FXy[i]in[1..8])Then{確定新坐標是否越界}IfRoad[x+Fxx[i],y+Fxy[i]]=0Thenbegin{判斷是否走過}Nx:=x+FXx[i];Ny:=y+FXy[i];Road[Nx,Ny]:=1;{建立新坐標}If(Nx=x1)and(Ny=y1)Theninc(total)elseFind(Nx,Ny);{遞歸}Road[Nx,Ny]:=0{回朔}endendEnd;BEGIN{Main}Total:=0;FillChar(Road,sizeof(road),0);Readln(x,y);{讀入開始坐標}Readln(x1,y1);{讀入結束坐標}If(x>10)or(y>10)or(x1>10)or(y1>10)Thenwriteln('Error'){判斷是否越界}ElseFind(x,y);Writeln('Total:',total){打出總數}END.這樣做是完全可行的,它輸入的是全部解,但是馬遍歷當8×8時解是非常之多的,用天文數字形容也不為過,這樣一來求解的過程就非常慢,並且出一個解也非常慢。
怎麼才能快速地得到部分解呢?
【貪心演算法】
其實馬踏棋盤的問題很早就有人提出,且早在1823年,J.C.Warnsdorff就提出了一個有名的演算法。在每個結點對其子結點進行選取時,優先選擇『出口』最小的進行搜索,『出口』的意思是在這些子結點中它們的可行子結點的個數,也就是『孫子』結點越少的越優先跳,為什麼要這樣選取,這是一種局部調整最優的做法,如果優先選擇出口多的子結點,那出口少的子結點就會越來越多,很可能出現『死』結點(顧名思義就是沒有出口又沒有跳過的結點),這樣對下面的搜索純粹是徒勞,這樣會浪費很多無用的時間,反過來如果每次都優先選擇出口少的結點跳,那出口少的結點就會越來越少,這樣跳成功的機會就更大一些。這種演算法稱為為貪心演算法,也叫貪婪演算法或啟發式演算法,它對整個求解過程的局部做最優調整,它只適用於求較優解或者部分解,而不能求最優解。這樣的調整方法叫貪心策略,至於什麼問題需要什麼樣的貪心策略是不確定的,具體問題具體分析。實驗可以證明馬遍歷問題在運用到了上面的貪心策略之後求解速率有非常明顯的提高,如果只要求出一個解甚至不用回溯就可以完成,因為在這個演算法提出的時候世界上還沒有計算機,這種方法完全可以用手工求出解來,其效率可想而知。

② 求一個演算法(貪心演算法)

貪心演算法

一、演算法思想

貪心法的基本思路:
——從問題的某一個初始解出發逐步逼近給定的目標,以盡可能快的地求得更好的解。當達到某演算法中的某一步不能再繼續前進時,演算法停止。
該演算法存在問題:
1. 不能保證求得的最後解是最佳的;
2. 不能用來求最大或最小解問題;
3. 只能求滿足某些約束條件的可行解的范圍。

實現該演算法的過程:
從問題的某一初始解出發;
while 能朝給定總目標前進一步 do
求出可行解的一個解元素;
由所有解元素組合成問題的一個可行解;

二、例題分析

1、[背包問題]有一個背包,背包容量是M=150。有7個物品,物品可以分割成任意大小。
要求盡可能讓裝入背包中的物品總價值最大,但不能超過總容量。

物品 A B C D E F G
重量 35 30 60 50 40 10 25
價值 10 40 30 50 35 40 30

分析:

目標函數: ∑pi最大
約束條件是裝入的物品總重量不超過背包容量:∑wi<=M( M=150)

(1)根據貪心的策略,每次挑選價值最大的物品裝入背包,得到的結果是否最優?
(2)每次挑選所佔重量最小的物品裝入是否能得到最優解?
(3)每次選取單位重量價值最大的物品,成為解本題的策略。 ?

值得注意的是,貪心演算法並不是完全不可以使用,貪心策略一旦經過證明成立後,它就是一種高效的演算法。
貪心演算法還是很常見的演算法之一,這是由於它簡單易行,構造貪心策略不是很困難。
可惜的是,它需要證明後才能真正運用到題目的演算法中。
一般來說,貪心演算法的證明圍繞著:整個問題的最優解一定由在貪心策略中存在的子問題的最優解得來的。
對於例題中的3種貪心策略,都是無法成立(無法被證明)的,解釋如下:
(1)貪心策略:選取價值最大者。反例:
W=30
物品:A B C
重量:28 12 12
價值:30 20 20
根據策略,首先選取物品A,接下來就無法再選取了,可是,選取B、C則更好。
(2)貪心策略:選取重量最小。它的反例與第一種策略的反例差不多。
(3)貪心策略:選取單位重量價值最大的物品。反例:
W=30
物品:A B C
重量:28 20 10
價值:28 20 10
根據策略,三種物品單位重量價值一樣,程序無法依據現有策略作出判斷,如果選擇A,則答案錯誤。

所以需要說明的是,貪心演算法可以與隨機化演算法一起使用,具體的例子就不再多舉了。(因為這一類演算法普及性不高,而且技術含量是非常高的,需要通過一些反例確定隨機的對象是什麼,隨機程度如何,但也是不能保證完全正確,只能是極大的幾率正確)

================================
三個經典的貪心演算法

有人說貪心演算法是最簡單的演算法,原因很簡單:你我其實都很貪,根本不用學。有人說貪心演算法是最復雜的演算法,原因也很簡單:這世上貪的人太多了,那輪到你我的份?

不論難度如何,貪心演算法都是一個很重要的演算法,我在網上N多Online Judge中的題目中,總結了三類較為常見,也十分經典的貪心演算法,發布在這兒Just For Fun。

(註:由於沒有現成的名字可用,這三種類型貪心演算法的名字都是我自己取的,如果你聽著別扭,請見諒。)

No 1.線段覆蓋(linescover)

題目大意:

在一維空間中告訴你N條線段的起始坐標與終止坐標,要求求出這些線段一共覆蓋了多大的長度。

解題思路:

將線段按其坐標進行排序(排序的具體方法:按起始坐標排,起始坐標相同的按終止坐標排,都是小在前大在後),使之依次遞增,並按順序分別編號為X(i),X(i).a代表其起始坐標,X(i).b代表其終止坐標。

然後按排好的順序依次處理:定義一個變數last記錄考慮到當前線段之時被線段覆蓋的最大的坐標值,再定義一個變數length記錄當前線段覆蓋的長度。對於後面的線段,我們把它看成由兩個部分組成,即把它分成last之前的線段和last之後的線段。(如果線段全部處在last之後,其last之前的部分不存在。)由於我們排過序,我們可以肯定當前考慮的線段X(i)其處在last之前的部分不會對length造成影響(因為X(i-1).b=last,X(i).a>=X(i-1).a,即X(i)在last之前的部分所處位置肯定被線段X(i-1)覆蓋過),所以會對length產生影響的即是X(i)處在last之後的部分。

所以我們可以依次對每條線段做如下處理:(初始化length為零,last為負無窮)

length+=X(i).b-last (X(i).a<=last 且 X(i).b>=last)

length+=X(i).b-X(i).a (X(i).a>last)

last=X(i).b;

最後length就為我們所需要的答案。

No 2.最優數對(bestpair)

題目大意:

按遞增的順序告訴你N個正整數和一個實數P,要求求出求出該數列中的比例最接近P的兩個數(保證絕對沒有兩個數使得其比值為P)。

解題思路:

定義兩個指針i和j,先初始化i=j=1,然後進行如下操作:

當code[j]/code[i]>p時,inc(j);

當code[j]/code[i]<p時,inc(i)。

記錄其中產生的最優值即為答案。

No 3.連續數之和最大值(maxsum)

題目大意:

給出一個長度為N的數列(數列中至少有一個正數),要求求出其中的連續數之和的最大值。(也可以加入a和b來限制連續數的長度不小於a且不大於b)。

解題思路:

先說不加限制的那種,定義一個統計變數tot,然後用循環進行如下操作:inc(tot,item) 其中如果出現tot<0的情況,則將tot賦值為0。在循環過程之中tot出現的最大值即為答案。

如果加入了限制條件的話,問題就變得難一些了(這句真的不是廢話)。為此我們先定義數組sum[i]來表示code[1]到code[i]之和(這樣的話code[a]~code[b]的和我們就可以用sum[b]-sum[a-1]來表示了。)。

再維護一個數組hash[i]來表示滿足條件的sum[a-1]的下標,並使之按遞增順序排列,這樣當前以第i的數為終止的數列的最大值肯定就是sum[i]-sum[hash[1]]。

現在我們來討論hash數組之中的數據需要滿足的條件和如何維護的具體問題:

當考慮到以第i個數為結尾時,hash[i]所表示的下標需要滿足的第一個條件就是題目規定的長度限制,我們需要實時的加入滿足長度規定的下標,刪除不符合要求的下標。其次,與不加限制條件時相同,若sum[i]-sum[hash[1]]的值小於零,則清空數組hash。

維護時可以這樣,當考慮到第i個數時,我們就將下標i-a+1加入到hash中,因為hash中原來已經排好序,因此我們我們可以用插入排序來維護hash的遞增性,然後我們考察hash[1],若hash[1]<i-b+1,則證明其已超出長度限制,我們就將其刪除,接著再考慮更新後的hash[1],如此重復直至找到一個滿足條件的hash[1]為止。

我們可以用鏈表來表示hash,這樣就可以減少數據加入和刪除時頻繁數據移動的時間消耗。

記錄下sum[i]-sum[hash[1]]的最大值即為答案。

③ C語言關於貪心演算法的(很簡單)

LZ在開始研究ACM嘛?
#include
int
least_num_cash(int
_money)
{
/*直接貪心,能用大張的鈔票盡量用大張的*/
int
ret=0;
while(_money!=0)
{
if(_money>=100)
{
_money-=100;
}
else
if(_money>=50)
{
_money-=50;
}
else
if(_money>=20)
{
_money-=20;
}
else
if(_money>=10)
{
_money-=10;
}
else
if(_money>=5)
{
_money-=5;
}
else
if(_money>=2)
{
_money-=2;
}
else
if(_money>=1)
{
_money-=1;
}
ret++;
}
return
ret;
}
int
main()
{
int
n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
printf("%d\n",least_num_cash(m-n));
}
return
0;
}

④ 貪心演算法,這個貪心到底是什麼意思

貪心指目光短淺,只看到當前這一步的最優決策,而不考慮以後的決策。這樣的演算法只在特定的問題下是正確的。

⑤ 單源最短路徑可以用貪心演算法得到最優解嗎

可以。對於權值大於等於零的有相或無相圖,可以使用基於貪心思想的Dijkstra演算法求解單源最短路徑問題。

⑥ 找零錢問題的貪心演算法

問題描述:
當前有面值分別為2角5分,1角,5分,1分的硬幣,請給出找n分錢的最佳方案(要求找出的硬幣數目最少)
問題分析:
根據常識,我們到店裡買東西找錢時,老闆總是先給我們最大面值的,要是不夠再找面值小一點的,直到找滿為止。如果老闆都給你找分數的或者幾角的,那你肯定不幹,另外,他也可能沒有那麼多零碎的錢給你找。其實這就是一個典型的貪心選擇問題。
問題的演算法設計與實現:
先舉個例子,假如老闆要找給我99分錢,他有上面的面值分別為25,10,5,1的硬幣數,為了找給我最少的硬幣數,那麼他是不是該這樣找呢,先看看該找多少個25分的, 99/25=3,好像是3個,要是4個的話,我們還得再給老闆一個1分的,我不幹,那麼老闆只能給我3個25分,由於還少給我24,所以還得給我2個10分的和4個1分。
具體實現
//找零錢演算法
//By falcon
//輸入:數組m,依次存放從大到小排列的面值數,n為需要找的錢數,單位全部為分
//輸出:數組num,對照數組m中的面值存放不同面值的硬幣的個數,即找錢方案

⑦ Python貪心演算法

所謂貪心演算法是指在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優加以考慮,它所做出的僅僅是在某種意義上的局部最優解。下面讓我們來看一個經典的例題。假設超市的收銀櫃中有1分、2分、5分、1角、2角、5角、1元的硬幣。
顧客結賬如果需要找零錢時,收銀員希望將最少的硬幣數找出給顧客,那麼,給定需要找的零錢數目,如何求得最少的硬幣數呢?這個找零錢的基本思路:每次都選擇面值不超過需要找給顧客的錢最大面值的硬幣。
我們可以從面值最大的硬幣開始,然後依次遞減(圖1)。
首先定義列表d存儲已有幣值。並且定義d_num存儲每種幣值的數量。通過循環遍歷的方法計算出收銀員擁有錢的總金額並保存在變數S中,要找的零錢變數為sum。當找零的金_比收銀員的總金額多時,無法進行找零,提示報錯。要想用的錢幣數量最少,我們從面值最大的幣值開始遍歷。這里也就是我們貪心演算法的核心步驟。計算出每種硬幣所需要的數量,不斷地更新硬幣個數與硬幣面值,最終獲得一個符合要求的組合(圖2)。
貪心演算法在對問題求解時,不是對所有問題都能得到整體最優解,也不是從整體上去考慮,做出的只是在某種意義上的局部最優解。從面值最大的硬幣開始依次遞減,尋找可用的方法。一般貪心演算法並不能保證是最佳的解決方法,這是因為:總是從局部出發沒有從整體考慮,只能確定某些問題是有解的,優點是演算法簡單。常用來解決求最大值或最小值的問題。來源:電腦報

⑧ 貪心演算法 單源點最短路徑 幫忙修改代碼

MGraph G,g;改成MGraph g;就行
你申請了兩張圖,每張圖都開了個90000個int的數組當然在棧里放不下,要麼只申請一張圖,要麼放在main外面當全局變數

⑨ 貪心演算法中的matlab演算法怎麼做

1.數論演算法
求兩數的最大公約數
function gcd(a,b:integer):integer;
begin
if b=0 then gcd:=a
else gcd:=gcd (b,a mod b);
end ;

求兩數的最小公倍數
function lcm(a,b:integer):integer;
begin
if a< b then swap(a,b);
lcm:=a;
while lcm mod b >0 do inc(lcm,a);
end;

素數的求法
A.小范圍內判斷一個數是否為質數:
function prime (n: integer): Boolean;
var I: integer;
begin
for I:=2 to trunc(sqrt(n)) do
if n mod I=0 then
begin
prime:=false; exit;
end;
prime:=true;
end;

B.判斷longint范圍內的數是否為素數(包含求50000以內的素數表):
procere getprime;
var
i,j:longint;
p:array[1..50000] of boolean;
begin
fillchar(p,sizeof(p),true);
p[1]:=false;
i:=2;
while i< 50000 do
begin
if p then
begin
j:=i*2;
while j< 50000 do
begin
p[j]:=false;
inc(j,i);
end;
end;
inc(i);
end;
l:=0;
for i:=1 to 50000 do
if p then
begin
inc(l);
pr[l]:=i;
end;
end;{getprime}
function prime(x:longint):integer;
var i:integer;
begin
prime:=false;
for i:=1 to l do
if pr >=x then break
else if x mod pr=0 then exit;
prime:=true;
end;{prime}

2.

3.

4.求最小生成樹
A.Prim演算法:
procere prim(v0:integer);
var
lowcost,closest:array[1..maxn] of integer;
i,j,k,min:integer;
begin
for i:=1 to n do
begin
lowcost:=cost[v0,i];
closest:=v0;
end;
for i:=1 to n-1 do
begin
{尋找離生成樹最近的未加入頂點k}
min:=maxlongint;
for j:=1 to n do
if (lowcost[j]< min) and (lowcost[j]< >0) then
begin
min:=lowcost[j];
k:=j;
end;
lowcost[k]:=0; {將頂點k加入生成樹}
{生成樹中增加一條新的邊k到closest[k]}
{修正各點的lowcost和closest值}
for j:=1 to n do
if cost[k,j]< lwocost[j] then
begin
lowcost[j]:=cost[k,j];
closest[j]:=k;
end;
end;
end;{prim}
B.Kruskal演算法:(貪心)
按權值遞增順序刪去圖中的邊,若不形成迴路則將此邊加入最小生成樹。
function find(v:integer):integer; {返回頂點v所在的集合}
var i:integer;
begin
i:=1;
while (i< =n) and (not v in vset) do inc(i);
if i< =n then find:=i
else find:=0;
end;
procere kruskal;
var
tot,i,j:integer;
begin
for i:=1 to n do vset:=;{初始化定義n個集合,第I個集合包含一個元素I}
p:=n-1; q:=1; tot:=0; {p為尚待加入的邊數,q為邊集指針}
sort;
{對所有邊按權值遞增排序,存於e[I]中,e[I].v1與e[I].v2為邊I所連接的兩個頂點的序號,e[I].len為第I條邊的長度}
while p >0 do
begin
i:=find(e[q].v1);j:=find(e[q].v2);
if i< >j then
begin
inc(tot,e[q].len);
vset:=vset+vset[j];vset[j]:=[];
dec(p);
end;
inc(q);
end;
writeln(tot);
end;

5.最短路徑
A.標號法求解單源點最短路徑:
var
a:array[1..maxn,1..maxn] of integer;
b:array[1..maxn] of integer; {b指頂點i到源點的最短路徑}
mark:array[1..maxn] of boolean;

procere bhf;
var
best,best_j:integer;
begin
fillchar(mark,sizeof(mark),false);
mark[1]:=true; b[1]:=0;{1為源點}
repeat
best:=0;
for i:=1 to n do
If mark then {對每一個已計算出最短路徑的點}
for j:=1 to n do
if (not mark[j]) and (a[i,j] >0) then
if (best=0) or (b+a[i,j]< best) then
begin
best:=b+a[i,j]; best_j:=j;
end;
if best >0 then
begin
b[best_j]:=best;mark[best_j]:=true;
end;
until best=0;
end;{bhf}

B.Floyed演算法求解所有頂點對之間的最短路徑:
procere floyed;
begin
for I:=1 to n do
for j:=1 to n do
if a[I,j] >0 then p[I,j]:=I else p[I,j]:=0;
{p[I,j]表示I到j的最短路徑上j的前驅結點}
for k:=1 to n do {枚舉中間結點}
for i:=1 to n do
for j:=1 to n do
if a[i,k]+a[j,k]< a[i,j] then
begin
a[i,j]:=a[i,k]+a[k,j];
p[I,j]:=p[k,j];
end;
end;
C. Dijkstra 演算法:
類似標號法,本質為貪心演算法。
var
a:array[1..maxn,1..maxn] of integer;
b,pre:array[1..maxn] of integer; {pre指最短路徑上I的前驅結點}
mark:array[1..maxn] of boolean;
procere dijkstra(v0:integer);
begin
fillchar(mark,sizeof(mark),false);
for i:=1 to n do
begin
d:=a[v0,i];
if d< >0 then pre:=v0 else pre:=0;
end;
mark[v0]:=true;
repeat {每循環一次加入一個離1集合最近的結點並調整其他結點的參數}
min:=maxint; u:=0; {u記錄離1集合最近的結點}
for i:=1 to n do
if (not mark) and (d< min) then
begin
u:=i; min:=d;
end;
if u< >0 then
begin
mark:=true;
for i:=1 to n do
if (not mark) and (a[u,i]+d< d) then
begin
d:=a[u,i]+d;
pre:=u;
end;
end;
until u=0;
end;
D.計算圖的傳遞閉包
Procere Longlink;
Var
T:array[1..maxn,1..maxn] of boolean;
Begin
Fillchar(t,sizeof(t),false);
For k:=1 to n do
For I:=1 to n do
For j:=1 to n do
T[I,j]:=t[I,j] or (t[I,k] and t[k,j]);
End;

⑩ 貪心演算法的數學應用

如把3/7和13/23分別化為三個單位分數的和
【貪心演算法】
設a、b為互質正整數,a<b 分數a/b 可用以下的步驟分解成若干個單位分數之和:
步驟一: 用b 除以a,得商數q1 及余數r1。(r1=b - a*q1)
步驟二:把a/b 記作:a/b=1/(q1+1)+(a-r1)/b(q1+1)
步驟三:重復步驟2,直到分解完畢
3/7=1/3+2/21=1/3+1/11+1/231
13/23=1/2+3/46=1/2+1/16+1/368
以上其實是數學家斐波那契提出的一種求解埃及分數的貪心演算法,准確的演算法表述應該是這樣的:
設某個真分數的分子為a,分母為b;
把b除以a的商部分加1後的值作為埃及分數的某一個分母c;
將a乘以c再減去b,作為新的a;
將b乘以c,得到新的b;
如果a大於1且能整除b,則最後一個分母為b/a;演算法結束;
或者,如果a等於1,則,最後一個分母為b;演算法結束;
否則重復上面的步驟。
備註:事實上,後面判斷a是否大於1和a是否等於1的兩個判斷可以合在一起,及判斷b%a是否等於0,最後一個分母為b/a,顯然是正確的。
PHP代碼: classtanxin{public$weight;public$price;publicfunction__construct($weight=0,$price=0){$this->weight=$weight;$this->price=$price;}}//生成數據$n=10;for($i=1;$i<=$n;$i++){$weight=rand(1,20);$price=rand(1,10);$x[$i]=newtanxin($weight,$price);}//輸出結果functiondisplay($x){$len=count($x);foreach($xas$val){echo$val->weight,'',$val->price;echo'<br>';}}//按照價格和重量比排序functiontsort(&$x){$len=count($x);for($i=1;$i<=$len;$i++){for($j=1;$j<=$len-$i;$j++){$temp=$x[$j];$res=$x[$j+1]->price/$x[$j+1]->weight;$temres=$temp->price/$temp->weight;if($res>$temres){$x[$j]=$x[$j+1];$x[$j+1]=$temp;}}}}//貪心演算法functiontanxin($x,$totalweight=50){$len=count($x);$allprice=0;for($i=1;$i<=$len;$i++){if($x[$i]->weight>$totalweight)break;else{$allprice+=$x[$i]->price;$totalweight=$totalweight-$x[$i]->weight;}}if($i<$len)$allprice+=$x[$i]->price*($totalweight/$x[$i]->weight);return$allprice;}tsort($x);//按非遞增次序排序display($x);//顯示echo'0-1背包最優解為:';echotanxin($x);java源代碼 packagemain;importjava.util.ArrayList;importjava.util.Collections;importjava.util.Comparator;importjava.util.List;importjava.util.Random;publicclassMain{/***測試*/publicstaticvoidmain(String[]args){//1.隨機構造一批任務List<Pair<Integer>>inputList=newArrayList<Pair<Integer>>();Randomrand=newRandom();for(intn=0;n<20;++n){Integerleft=rand.nextInt(100);Integerright=left+rand.nextInt(100)+1;Pair<Integer>pair=newPair<Integer>(left,right);inputList.add(pair);}//將任務列表按結束時間排序(也就是根據right欄位進行排序)sortByRight(inputList);printPairList(inputList);//執行演算法List<Pair<Integer>>outputList=algorithm(inputList);System.out.println();printPairList(outputList);}/***貪心演算法**@paraminputList*@return使數量最多的任務方案*/publicstatic<TextendsComparable<T>>List<Pair<T>>algorithm(List<Pair<T>>inputList){if(null==inputList||inputList.size()==0||inputList.size()==1){returninputList;}sortByRight(inputList);List<Pair<T>>outputList=newArrayList<Pair<T>>();intlast=0;outputList.add(inputList.get(last));intintputSize=inputList.size();for(intm=1;m<intputSize;++m){Pair<T>nextPair=inputList.get(m);TnextLeft=nextPair.getLeft();Pair<T>lastOutPair=inputList.get(last);TlastRight=lastOutPair.getRight();intflag=nextLeft.compareTo(lastRight);if(flag>=0){outputList.add(nextPair);last=m;}}returnoutputList;}/***對傳入的List<Pair<T>>對象進行排序,使Pair根據right從小到大排序。**@paraminputList*/privatestatic<TextendsComparable<T>>voidsortByRight(List<Pair<T>>inputList){CompareByRight<T>comparator=newCompareByRight<T>();Collections.sort(inputList,comparator);}/***列印一個List<Pair<T>>對象。**@paraminputList*/privatestatic<TextendsComparable<T>>voidprintPairList(List<Pair<T>>inputList){for(Pair<T>pair:inputList){System.out.println(pair.toString());}}}/***根據Pair.right比較兩個Pair。用於Conlections.sort()方法。**@param<T>*/classCompareByRight<TextendsComparable<T>>implementsComparator<Pair<T>>{/*@Override*/publicintcompare(Pair<T>o1,Pair<T>o2){Tr1=o1.getRight();Tr2=o2.getRight();intflag=r1.compareTo(r2);returnflag;}}/***代表一個任務對象。有點裝逼用模板來寫了。left表示開始時間,right表示結束時間。**@param<T>*/classPair<TextendsComparable<T>>{privateTleft;privateTright;publicPair(Tleft,Tright){this.left=left;this.right=right;}@OverridepublicStringtoString(){return[left=+left.toString()+','+right=+right.toString()+']';}publicTgetLeft(){returnleft;}publicvoidsetLeft(Tleft){this.left=left;}publicTgetRight(){returnright;}publicvoidsetRight(Tright){this.right=right;}}

熱點內容
erpjava 發布:2024-11-14 23:52:23 瀏覽:252
電腦版地平線四怎麼連上伺服器 發布:2024-11-14 23:46:42 瀏覽:471
ios怎麼變安卓 發布:2024-11-14 23:46:36 瀏覽:332
win7共享xp列印機拒絕訪問 發布:2024-11-14 23:45:29 瀏覽:749
引起資源配置失效的原因有哪些 發布:2024-11-14 23:35:22 瀏覽:14
c語言打字 發布:2024-11-14 23:11:06 瀏覽:892
存儲程序和程序控制的原理 發布:2024-11-14 22:53:23 瀏覽:322
python讀取json數據 發布:2024-11-14 22:51:52 瀏覽:931
釘線畫演算法 發布:2024-11-14 22:24:59 瀏覽:47
應用一直獲取配置失敗是怎麼回事 發布:2024-11-14 22:24:12 瀏覽:148