算法:分治总结

  分治法的基本思想:把一个规模为n的问题分解为k个规模较小的自问题,这些子问题互相独立且与原问题相同。

  一般的算法设计模式:

 Divide-and-Conquer(P)

{

  if(|P|<=n0)

  Adhoc(P);

  divide P into smaller subinstances

  P1,P2,...,Pk;

  for(int i = 1;i <= k;++i)

  yi = Divide-and-Conquer(Pi);

  return Merge(y1,y2,...,yk);

}

|P|表示问题的规格

n0表示当P规模不超过n0那么问题就已经容易解决不需要去分解

Adhoc(P)是该分治算法的基本子算法,当规模不超过n0就可以直接用它得出结果

Merge()的作用是该分治算法中的合并子算法,将所有子问题的解合并成P的解

例子,就是一个合并排序

template<class Type>
void Merge(Type *sd,Type *si,int left,int m,int right)
{
int i = left,j = m+1;
int k = left;
while(i<=m && j<= right)
{
sd[k++] = si[i] < si[j]? si[i++]:si[j++];
}
while(i<=m)
{
sd[k++] = si[i++];
}
while(j<=right)
{
sd[k++] = si[j++];
}
}


template<class Type>
void MergePass(Type *ar,Type *br,int n,int s)
{// s = 2;
// 0 1 2 3 //4 5 6 7 //8 9
cout<<"s = "<<s<<endl;
for(int i = 0;i+2*s-1 <= n-1; i+=2*s)
{
Merge(ar,br,i,i+s-1,i+2*s-1);
cout<<i<<" "<<i+s-1<<" "<<i+2*s-1<<endl;
}
if(n-1 > i+s-1)
{
Merge(ar,br,i,i+s-1,n-1);
cout<<i<<" "<<i+s-1<<" "<<n-1<<endl;
}
else//两个作用,一个是预防后面没有值了,还有一个是确保br给了ar,这个看后面你就懂了
{
for(int j = i;j<n;++j)
{
ar[j] = br[j];
}
}
Print_Array(ar,n);
}


template<class Type>
void MergeSort(Type *ar,int n)
{
Type *br = new Type[n];
int s = 1;
while(s < n)
{
MergePass(br,ar,n,s);//分治,分成小段小段,顺便的MergePass完成了分治中的合并子算法,和子算法的计算
s+=s;
MergePass(ar,br,n,s);//同上,顺便把所有数据给ar
s+=s;
}
delete []br;
}


在用分治法设计算法时,最好使子问题的规模大致相同,即将一个问题分成大小相等的k个子问题的处理方法是行之有效的。

分治算法棋盘覆盖的思路:

采用的是L型骨牌覆盖棋盘

(1)先看2*2,有一个点和其他的不同,另外三个被同一个L给覆盖了

(2)递推2^2*2^2,如果左上的2*2有,那么[1][2],[2][2],[2][1]构成了一个L,然后再分看,四个部分各一个L就补全了

要是8*8那么[3][4],[4][3],[4][4],找出规律,n*n,[n/2-1][n/2],[n/2][n/2-1],[n][n]构成第一个,然后n=n/2,一直到n=1为止

void CheseBoard(Array ar,int tr,int tc,int dr,int dc,int size)

dr,dc表示特殊点所在的位置,行列,tr,tc,棋盘左上角放个行号,棋盘左上角方格列号










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值