分治算法

一、概述

分治算法說白了就是把一個大型問題轉化爲小問題逐個解決。

個人感覺和分治算法含有遞歸的意味。

一般步驟:

(1)分解,將要解決的問題劃分成若干規模較小的同類問題;

(2)求解,當子問題劃分得足夠小時,用較簡單的方法解決;

(3)合併,按原問題的要求,將子問題的解逐層合併構成原問題的解。

總之,分治可以產生貪心,二分,線段樹等問題。

說實話,分治算法是一種思想,沒有什麼特定的代碼框架。

接下來我們來看一些使用分治算法的經典問題。

二、二分找數

二分是一種求極值的算法,通常已知答案的取值範圍,枚舉範圍中點,並逐步縮小範圍。

舉個例子:員工小C和志熊在一起快樂吃雞,兩人決賽圈想當伏地魔而不專心,玩起了猜子彈遊戲。

當然,小C是個新手,而系統自動拾取子彈,所以自己從來不關心自己有多少子彈(只是看有拾取標識就點);志熊是個黃金,知道系統認爲同一種撿200發就夠了,那志熊每一次猜測的最優解是什麼呢?

自然是先猜(1+200)/2=100發了,這樣有可能一次猜中(機率很小,歐吃矛),但更多的好處在於可以立刻縮減最非時的最大範圍。於是這樣每次猜正中間,很快便能找到答案,而且思維比較規範,不會亂。

這就是分治算法的體現。

代碼主要結構如下,各有各的寫法:

int search(int goal);
{
	int l=1,r=n;
    while(l<=r)
    {
    	int mid=(l+r)/2;
    	if(a[mid]==goal) return mid;
    	else if(a[mid]>goal) r=mid-1;
    	else l=mid+1;
    }
    return -1;
}

三、快排 

已經厭倦 algorithm 中的sort的OIER以及與時間賽跑的dalao可以試試手打快排。

快排是當前對於部分問題來說,確實是所有排序方法中最優解之一。

代碼貼一下吧:

void qsort(int l,int r)
{
	int i,j,mid,p;
	i=l;j=r;
	mid=a[(l+r)/2];
	do
	{
		while (a[i]<mid) i++;
		while (a[j]>mid) j--;
		if (o<=j)
		{
			p=a[i];a[i]=a[j];a[j]=p;
			i++;j--;
		}
	}while(i<=j);
	if (l<j) qsort(l,j);
	if (i<r) qsort(i,r);
}

 

四、總結

這個思想比較巧妙,大家可以寫一些這幾道題,比較有趣,分治思想也比較明顯。

[HNOI2006]鬼谷子的錢袋

洛谷 P1010 冪次方

洛谷 P1908 逆序對

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章