分治
分治法的三個步驟
- 分解:將原問題分解爲和若干原問題擁有相同或者相似結構的子問題
- 解決:遞歸求解所有子問題。如果存在子問題的規模小到可以直接解決,就直接解決它。
- 合併:將子問題的解合併爲原問題的解。
注意:分治法分解出的子問題應當是相互獨立,沒有交叉的。
分治法作爲一種算法思想,既可以使用遞歸的手段來實現,也可以使用非遞歸的手段來實現,可以是具體情況來定,一般來說,使用遞歸實現較爲容易。
遞歸
遞歸邏輯中的兩個重要概念:
- 遞歸邊界
- 遞歸式(護着成爲遞歸調用)
求解n的階乘
#include<iostream>
using namespace std;
int F(int n)
{
if(n==0) return 1;
else return F(n-1)*n;
}
int main()
{
int n;
cin>>n;
cout<<F(n);
return 0;
}
求斐波那契數列的第n項
#include<iostream>
using namespace std;
int F(int n){
if(n==1||n==0) return 1;
else return F(n-1)+F(n-2);
}
int main()
{
int n;
cin>>n;
cout<<F(n);
return 0;
}
輸出1~n這n個整數的全排列
#include<iostream>
using namespace std;
const int maxn=11;
int n,index,P[maxn],hashTable[maxn]={false};
void generateP(int index)
{
if(index==n+1)
{
for(int i=1;i<=n;i++)
{
cout<<P[i];
}
cout<<endl;
}
for(int i=1;i<=n;i++)
{
if(hashTable[i]==false)
{
P[index]=i;
hashTable[index]=true;
generateP(index+1);
hashTable[index]=false;
}
}
}
int main()
{
cin>>n;
generateP(1);
return 0;
}
N皇后問題(樸素法)
int count=0;
void generateP(index)
{
bool flag=true;
if(index==n+1)
{
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(abs(a-b)==abs(P[i]-P[j])) flag=false;
}
}
if(flag==true) count++;
return ;
}
for(int i=1;i<=n;i++)
{
if(hashTable[i]==false)
{
P[index]=i;
hashTable[i]=true;
generateP(index+1);
hashTable[i]=flase;
}
}
}
N皇后問題(回溯法)
int count=0;
void generateP(int index)
{
if(index=n+1)
{
count++;
return;
}
for(int i=1;i<=n;i++)
{
if(hashTable[i]==false)
{
bool flag=true;
for(int j=1;j<index;j++)
{
if(abs(index-j)==abs(i-P[j]))
{
flag=false;
break;
}
}
if(flag=true)
{
P[index]=i;
hashTable[i]=true;
generateP(index+1);
hashTable[i]=false;
}
}
}
}