概念
分治算法的基本思想是將一個大的復雜的問題分解成多個小的、容易解決的問題,通過解決這些小問題進而解決這個大問題。
使用分治算法需要待求解問題能夠簡化為若干個小規模的相同的問題,通過逐步划分,達到一個易於求解的階段,而直接進行求解,在程序中可以使用遞歸方法來進行求解。
哈哈,說起來很抽象,舉個例子就好理解了。
一個袋子里有n個硬幣,其中一枚是假幣,並且假幣和真幣一模一樣,僅憑肉眼無法區分,僅知道假幣比真幣輕一些,請問如何查找到假幣?
分治算法:
我們可以這樣做:
將這n個硬幣分成兩等份,然后放到天平的兩端,則假幣在較輕的那一端;
然后將較輕的那一端的硬幣再分成2等份,然后再放到天平的兩端進行比較,假幣還是在較輕的那一段;
直到最后只剩下兩個硬幣了,分別放到天平的兩端,輕的哪一個就是假幣。
當然,最后也可能剩下3個硬幣,我們可以將這3個硬幣中任意拿出來一個,然后將剩下的兩個放到天平的兩端,如果天平是平的,則說明拿出來的那個硬幣就是假幣;
如果天平不是平的,則輕的那一端是假幣。
C++語言程序代碼:
#include<iostream> using namespace std; /**************定義查找硬幣的函數find_false()**********************/ int find_false(int a[],int low,int high) { int i=0; //作為遍歷的計數器 int re=0; //re作為返回值 int sum1,sum2,sum3; //三個用來累加的變量 sum1=sum2=sum3=0; if(low+1==high) //當遍歷到最后兩個元素的時候 { if(a[low]<a[high]) { re=low; return re; } else { re=high; return re; } } if((high-low+1)%2==0) //當長度為偶數的時候 { for(i=low;i<=low+(high-low+1)/2-1;i++) //對前半段求和 { sum1+=a[i]; } for(i=low+(high-low+1)/2;i<=high;i++) //對后半段求和 { sum2+=a[i]; } if(sum1<sum2) //假幣在前半段 { re=find_false(a,low,low+(high-low+1)/2-1); return re; } else if(sum2<sum1) //假幣在后半段 { re=find_false(a,low+(high-low+1)/2,high); return re; } } else //當長度為奇數的時候 { for(i=low;i<=low+(high-low)/2-1;i++) //對前半段求和 { sum1+=a[i]; } for(i=low+(high-low)/2+1;i<=high;i++)//對后半段求和 { sum2+=a[i]; } sum3=a[low+(high-low)/2]; //sum3用於存放中間數據 if(sum1<sum2) //假幣在前半段 { re=find_false(a,low,low+(high-low)/2-1); return re; } else if(sum2>sum1) { re=find_false(a,low+(high-low)/2,high); return re; } else if(sum1+sum3==sum2+sum3) //中間的那個就是假幣! { re=(high-low)/2+1; return re; } } } int main() { int a[100]; int n,i,re; cout<<"請輸入硬幣的個數:"; cin>>n; cout<<"請分別輸入這個"<<n<<"個硬幣的重量:"<<endl; for(i=1;i<=n;i++) { cin>>a[i]; } re=find_false(a,1,n); cout<<"假幣是第"<<re<<"硬幣"<<endl; return 0; }
程序運行結果: