Ⅰ 浙大ACM第2416我用貪心演算法做的為什麼不對,希望高手解答
傳統bfs的題目,貪心不一定對,請問樓主能給出證明嗎
Ⅱ 貪心演算法 活動安排問題
這道題的貪心演算法比較容易理解,我就不多說明了,只是提到一下演算法思路1、建立數學模型描述問題。我在這里將時間理解成一條直線,上面有若干個點,可能是某些活動的起始時間點,或終止時間點。在具體一下,如果編程來實現的話,將時間抽象成鏈表數組,數組下標代表其實時間,該下標對應的鏈表代表在這個時間起始的活動都有哪些,具體參照程序注釋。2、問題分解。為了安排更多的活動,那麼每次選取佔用時間最少的活動就好。那麼從一開始就選取結束時間最早的,然後尋找在這個時間點上起始的活動,以此類推就可以找出貪心解。程序代碼:#include<stdio.h>
struct inode //自定義的結構體
{
int end; //表示結束時間
inode *next; //指向下一個節點的指針
};int main()
{
inode start[10001],*pt;
int a,b,i,num=0; //num負責計數,i控制循環,a,b輸入時候使用
for(i=0;i<10001;i++) //初始化
{
start[i].next=NULL;
}
while(scanf("%d %d",&a,&b)) //輸入並建立數據結構
{
if(a==0&&b==0) break;
pt=new inode; //創建新的節點,然後將該節點插入相應的位置
pt->end=b;
pt->next=start[a].next;
start[a].next=pt;
}
i=0;
while(i<10001) //進行貪心演算法,i表示當前時間
{
if(start[i].next==NULL)
{
i++; //該時間無活動開始
}
else
{
int temp=10001; //臨時變數,存儲該鏈表中最早的終止時間
for(pt=start[i].next;pt!=NULL;pt=pt->next)
{
if(pt->end<temp)
{
temp=pt->end;
}
}
i=temp; //將當前時間設置成前一子問題的終止時間
num++;
}
}
printf("%d\n",num); //列印結果
return 0;
}代碼並不一定是最快速的,但是可以求出貪心解,如果你做的是ACM編程題目,不保證能AC注釋我盡力寫了,希望對你有幫助。
Ⅲ 如何用貪心演算法解決磁碟文件最優存儲問題
dp??
方程為
a(fi,fj)=min{(a(fi,fk)+a(fk,fj)),a(fi,fj)}(k=i+1,i+2...j-1);
Ⅳ 貪心演算法
平面點集三角剖分的貪心演算法要求三角剖分後邊的總長度盡可能小。演算法的基本思想是將所有的兩點間距離從小到大排序,依次序每次取一條三角剖分的邊,直至達到要求的邊數。以下是兩種貪心演算法的主要步驟。
3.2.2.1 貪心演算法1
第一步:設置一個記錄三角剖分中邊的數組T。
第二步:計算點集S中所有點對之間的距離d(pi,pj),1≤i,j≤n,i≠j,並且對距離從小到大進行排序,設為d1,d2,…,dn(n-1)/2,相應的線段記為e1,e2,…,en(n-1)/2,將這些線段存儲在數組E中。
第三步:從線段集E中取出長度最短的邊e1存到T中作為三角剖分的第一條邊,此時k=1。
第四步:依次從E中取出長度最短的邊ek,與T中已有的邊進行求交運算,如果不相交則存到T中,並從E中刪除ek。這一步運行到S中沒有邊為止,即至k=n(n-1)/2。
第五步:輸出T。
該演算法中,第二步需要計算n(n-1)/2次距離,另外距離排序需要O(n2lgn)次比較。T中元素隨第四步循環次數的增加而增加,因此向T中加入一條新邊所需要的判定兩條線段是否相交的次數也隨之增加。如果第四步的前3n-6次循環後已經構成點集的三角剖分,那麼第四步循環所需要的判定兩條線段是否相交的次數為
1+2+…+3n-7+(3n-6)×(n(n-1)/2-(3n-6))=O(n3)
在常數時間內可以判定兩條線段是否相交,因此該演算法的時間復雜性為O(n3)。
3.2.2.2 貪心演算法2
第一步:求點集的凸殼,設凸殼頂點為p1,p2,…,pm,凸殼的邊為e1,e2,…,em。並將凸殼頂點按順序連接成邊的ei加入T(三角剖分的邊集合),並且ei的權值被賦為1。凸殼內點的集合為S1={pm+1,pm+2,…,pn}。
第二步:從內部點S1中任取一點pi,求與pi距離最近的點pj,將線段 存入T。
第三步:求與pj距離最近的點(除點pi外),設為pk,並將線段 加入T,並將這些邊的權值設為1,而wij、wjk和wki的值加1,即為2。邊的權值為2則表示該邊為兩個三角形共有。
第五步:對權值為1的邊(除e1,e2,…,em外)的兩個端點分別求與其距離最近的點,並將其連線(得到新的三角形)加入T,新三角形邊的權值加1。
第六步:對權值為1的邊重復上一步,當一條邊被使用一次其權值增加1,直到所有邊的權值均為2為止(除e1,e2,…,em外)。
貪心演算法2中,第一步耗費O(nlgn);第二步需要計算n-1次距離與n-2次比較;第三步求pk要計算n-2次的距離與n-3次比較;第四步要進行(n-3)×3次的距離計算及(n-4)×3次比較;第五步至多進行n-6次的距離計算與n-7次比較;第六步到第五步的循環次數不超過3n-9;因此整個貪心演算法2的時間復雜性為
O(nlgn)+O(n)+O(n)+O(n)+(n-6)×(3n-9)=O(n2)
Ⅳ 貪心演算法實現哈夫曼編碼
// 哈夫曼編碼(演算法)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char *HuffmanCode; //動態分配數組,存儲哈夫曼編碼
typedef struct
{
unsigned int weight; //用來存放各個結點的權值
unsigned int parent,LChild,RChild; //指向雙親、孩子結點的指針
} HTNode, *HuffmanTree; //動態分配數組,存儲哈夫曼樹
//選擇兩個parent為0,且weight最小的結點s1和s2
void Select(HuffmanTree *ht,int n,int *s1,int *s2)
{
int i,min;
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0)
{
min=i;
break;
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0)
{
if((*ht)[i].weight<(*ht)[min].weight)
min=i;
}
}
*s1=min;
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0 && i!=(*s1))
{
min=i;
break;
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent==0 && i!=(*s1))
{
if((*ht)[i].weight<(*ht)[min].weight) min=i;
}
}
*s2=min;
}
//構造哈夫曼樹ht。w存放已知的n個權值
void CrtHuffmanTree(HuffmanTree *ht,int *w,int n)
{
int m,i,s1,s2;
m=2*n-1;
*ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(i=1; i<=n; i++) //1--n號存放葉子結點,初始化
{
(*ht)[i].weight=w[i];
(*ht)[i].LChild=0;
(*ht)[i].parent=0;
(*ht)[i].RChild=0;
}
for(i=n+1; i<=m; i++)
{
(*ht)[i].weight=0;
(*ht)[i].LChild=0;
(*ht)[i].parent=0;
(*ht)[i].RChild=0;
} //非葉子結點初始化
printf("\nHuffmanTree: \n");
for(i=n+1; i<=m; i++) //創建非葉子結點,建哈夫曼樹
{ //在(*ht)[1]~(*ht)[i-1]的范圍內選擇兩個parent為0
//且weight最小的結點,其序號分別賦值給s1、s2
Select(ht,i-1,&s1,&s2);
(*ht)[s1].parent=i;
(*ht)[s2].parent=i;
(*ht)[i].LChild=s1;
(*ht)[i].RChild=s2;
(*ht)[i].weight=(*ht)[s1].weight+(*ht)[s2].weight;
printf("%d (%d, %d)\n",(*ht)[i].weight,(*ht)[s1].weight,(*ht)[s2].weight);
}
printf("\n");
} //哈夫曼樹建立完畢
//從葉子結點到根,逆向求每個葉子結點對應的哈夫曼編碼
void CrtHuffmanCode(HuffmanTree *ht, HuffmanCode *hc, int n)
{
char *cd;
int i,start,p;
unsigned int c;
hc=(HuffmanCode *)malloc((n+1)*sizeof(char *)); //分配n個編碼的頭指針
cd=(char *)malloc(n*sizeof(char)); //分配求當前編碼的工作空間
cd[n-1]='\0'; //從右向左逐位存放編碼,首先存放編碼結束符
for(i=1; i<=n; i++) //求n個葉子結點對應的哈夫曼編碼
{
start=n-1; //初始化編碼起始指針
for(c=i,p=(*ht)[i].parent; p!=0; c=p,p=(*ht)[p].parent) //從葉子到根結點求編碼
if( (*ht)[p].LChild==c) cd[--start]='0'; //左分支標0
else cd[--start]='1'; //右分支標1
hc[i]=(char *)malloc((n-start)*sizeof(char)); //為第i個編碼分配空間
strcpy(hc[i],&cd[start]);
}
free(cd);
for(i=1; i<=n; i++)
printf("HuffmanCode of %3d is %s\n",(*ht)[i].weight,hc[i]);
printf("\n");
}
void main()
{
HuffmanTree HT;
HuffmanCode HC;
int *w,i,n,wei,m;
printf("\nn = " );
scanf("%d",&n);
w=(int *)malloc((n+1)*sizeof(int));
printf("\ninput the %d element's weight:\n",n);
for(i=1; i<=n; i++)
{
printf("%d: ",i);
fflush(stdin);
scanf("%d",&wei);
w[i]=wei;
}
CrtHuffmanTree(&HT,w,n);
CrtHuffmanCode(&HT,&HC,n);
}
Ⅵ Python貪心演算法
所謂貪心演算法是指在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優加以考慮,它所做出的僅僅是在某種意義上的局部最優解。下面讓我們來看一個經典的例題。假設超市的收銀櫃中有1分、2分、5分、1角、2角、5角、1元的硬幣。
顧客結賬如果需要找零錢時,收銀員希望將最少的硬幣數找出給顧客,那麼,給定需要找的零錢數目,如何求得最少的硬幣數呢?這個找零錢的基本思路:每次都選擇面值不超過需要找給顧客的錢最大面值的硬幣。
我們可以從面值最大的硬幣開始,然後依次遞減(圖1)。
首先定義列表d存儲已有幣值。並且定義d_num存儲每種幣值的數量。通過循環遍歷的方法計算出收銀員擁有錢的總金額並保存在變數S中,要找的零錢變數為sum。當找零的金_比收銀員的總金額多時,無法進行找零,提示報錯。要想用的錢幣數量最少,我們從面值最大的幣值開始遍歷。這里也就是我們貪心演算法的核心步驟。計算出每種硬幣所需要的數量,不斷地更新硬幣個數與硬幣面值,最終獲得一個符合要求的組合(圖2)。
貪心演算法在對問題求解時,不是對所有問題都能得到整體最優解,也不是從整體上去考慮,做出的只是在某種意義上的局部最優解。從面值最大的硬幣開始依次遞減,尋找可用的方法。一般貪心演算法並不能保證是最佳的解決方法,這是因為:總是從局部出發沒有從整體考慮,只能確定某些問題是有解的,優點是演算法簡單。常用來解決求最大值或最小值的問題。來源:電腦報
Ⅶ 貪心演算法 如何解答三值排序問題 [IOI 1996]
題解(from USACO)
三值排序問題 [IOI 1996]
有一個由N個數值均為1、2或3的數構成的序列(N<= 1000),其值無序,現要求你用最少的交換次數將序列按升序順序排列。
演算法:排序後的序列分為三個部分:排序後應存儲1的部分,排序後應存儲2的部分和排序後應存儲3的部分,貪心排序法應交換盡量多的交換後位置正確的(2,1)、(3,1)和(3,2)數對。當這些數對交換完畢後,再交換進行兩次交換後位置正確的(1,2,3)三個數。
分析:很明顯,每一次交換都可以改變兩個數的位置,若經過一次交換以後,兩個數的位置都由錯誤變為了正確,那麼它必定最優。同時我們還可發現,經過兩次交換後,我們可以隨意改變3個數的位置。那麼如果存在三個數恰好為1,2和3,且位置都是錯誤的,那麼進行兩次交換使它們位置正確也必定最優。有由於該題具有最優子結構性質,我們的貪心演算法成立
程序:
var a:array[1..1000] of integer;
f:array[1..3,1..3] of integer;
b:array[1..3] of integer;
n,i,j,t,p:integer;
begin
readln(n);
for i:=1 to n do readln(a[i]);
fillchar(f,sizeof(f),0);
for i:=1 to n do inc(b[a[i]]);
b[2]:=b[2]+b[1];
b[3]:=n;
t:=0;
for i:=1 to n do
if i<=b[1] then inc(f[1,a[i]]) else
if i<=b[2] then inc(f[2,a[i]]) else
if i<=b[3] then inc(f[3,a[i]]);
for i:=1 to 2 do
for j:=i+1 to 3 do
begin
if f[i,j]>f[j,i] then p:=f[j,i] else p:=f[i,j];
t:=t+p;
if f[i,j]-p>=0 then f[i,j]:=f[i,j]-p;
if f[j,i]-p>=0 then f[j,i]:=f[j,i]-p;
end;
t:=t+(f[1,2]+f[1,3]) shl 1;
writeln(t);
end.
另外,站長團上有產品團購,便宜有保證
Ⅷ 請教一道貪心演算法的題目
貌似用不到貪心吧?
要求最少需要多少輛汽車只需確定最多有多少個乘客同時在車上就成了
演算法如下:
1,定義a[n][n]用於存儲p(i,j), 則i行的和為i站上車的人數, j列的和為j站下車的人數;
2,任意站點i開車時乘客人數f(i)=f(i-1)-d(i)+u(i),其中d(i)表示下車人數,u(i)表示上車人數,明顯f(0)=0;
3,從i=1開始到i=n-1結束,遍歷, 得到最多乘車的乘客數目max, 需要的車數=max/30 向上取整。
Ⅸ 求貪心演算法題(Pascal)
《編程之美》裡面有一道買書問題的貪心演算法。
題目是這樣的:
在節假日的時候,書店一般都會做促銷活動。由於《哈利波特》系列相當暢銷,店長決定通過促銷活動來回饋讀者。上櫃的《哈利波特》平裝本系列中,一共有五卷。假設每一卷單獨銷售均需8歐元 。如果讀者一次購買不同的兩卷,就可以扣除5%的費用,三卷則更多。假設具體折扣的情況如下:
本數 折扣
2 5%
3 10%
4 20%
5 25%
在一份訂單中,根據購買的卷數及本數,就會出現可以應用不同折扣規則的情況。但是,一本書只會應用一個折扣規則。比如,讀者一共買了兩本卷一,一本卷二。那麼,可以享受到5%的折扣。另外一本卷一則不能享受折扣。如果有多種折扣,希望計算出的總額盡可能的低。
要求根據以上需求,設計出演算法,能夠計算出讀者所購買一批書的最低價格。