在分治策略中,我们递归地求解一个问题,每层递归应用如下步骤:
(1)、分解:划分为一些子问题,子问题的形式与原问题一致,规模更小
(2)、解决:递归求解子问题,当子问题足够小的时候,停止递归直接求解
(3)、合并:将子问题的解组合成原问题
当子问题足够大,需要递归求解时,我们称之为递归情况;当子问题变得足够小,不需要递归时,称之为基本情况
并归排序
void Merge(int a[], int l, int mid, int r)
{
int i, j, k;
int n = mid - l + 1, m = r - mid; //左右数组长度
int L[50], R[50];
for (i = 0; i <n; i++)
L[i] = a[l + i];
for (i = 0; i < m; i++)
R[i] = a[mid + i+1];
L[n + 1] = inf; //防止哨兵,防止出现空数组
R[m + 1] = inf;
i = j =0;
while (i < n && j < m) //按顺序放回a数组
{
if (L[i] <= R[j])
{
a[l++] = L[i++];
}
else
{
a[l++] = R[j++];
}
}
while (i < n)
a[l++] = L[i++];
while (j < m)
a[l++] = R[j++];
}
void Merge_Sort(int a[], int l, int r)
{
if (l < r)
{
int mid = (l + r) / 2;
merge_Sort(a, l, mid);
merge_Sort(a, mid + 1, r);
merge(a, l, mid, r);
}
}
最大子数组(P1115 最大子段和 - 洛谷)
把一个数组分解成为两个部分,则最大子数组出现有三种情况:
全在左边数组;全在右边数组;跨过两个数组
对前两种递归到最小,第三种直接求解
struct node
{
int l, r, sum;
};
int a[maxn];
node findmid(int l, int mid, int r)
{
node midx;
int leftSum = -inf;
int sum = 0;
for (int i = mid; i >= l; i--)
{
sum += a[i];
if (sum > leftSum)
{
leftSum = sum;
midx.l = i;
}
}
int rightSum = -inf;
sum = 0;
for (int i = mid+1; i<=r; i++)
{
sum += a[i];
if (sum > rightSum)
{
rightSum = sum;
midx.r = i;
}
}
midx.sum = leftSum + rightSum;
return midx;
}
node findmax(int l, int r)
{
if (l == r) //解决(基本情况)
return { l,r,a[l] };
int mid = (l + r) / 2; //分解
node maxl = findmax(l, mid);
node maxr = findmax(mid + 1, r);
node maxm = findmid(l, mid, r);
int maxsum = max(max(maxl.sum, maxr.sum), maxm.sum); //合并
if (maxsum == maxl.sum)
return maxl;
if (maxsum == maxr.sum)
return maxr;
return maxm;
}
矩阵乘法的Strassen算法
类似分块矩阵的思路,但是并不优于直接计算,所以还需要一些公式,可以达到n的lg7次方复杂度