分治算法、动态规划算法、贪心算法
分治算法
该算法的字面解释是“分而治之”的意思,就是把一个复杂的问题分成两个或多个更多相同或相似的问题,再把子问题分成更小的子问题......直到
最后可以直接求解子问题,原问题的解即子问题的解的合并。
对于一个规模为n的问题,若该问题可以容易的解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立
且与原问题形式相同,递归的解这些子问题,然后将各子问题的解合并得到原问题的解,这种算法设计策略叫做分值算法。
分支算法能解决的问题一般具有如下的特征:
(1)该问题的规模缩小到一定程度就可以容易的解决;
(2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;(前提)
(3)利用该问题分解出的子问题的解可以合并为该问题的解;
(4)该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。
分治算法的三个步骤如下:
(1)分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
(2)解决:若子问题规模较小而容易被解决则直接解,否则递归来解各个子问题;
(3)合并:将各个子问题的解合并为原问题的解;
#include <stdio.h>
#include <stdlib.h>
int partion(int R[],int low,int high)
{
int a = R[low];
while(low<high)
{
while(low < high && R[high] > a)
{
high--;
}
if(low < high)
{
R[low] = R[high];
low++;
}
while(low <high && R[low] < a)
low++;
if(low < high)
{
R[high] = R[low] ;
high--;
}
}
R[low] = a;
return low;
}
void SwapSortB(int R[],int b ,int c)
{
int i;
if(b<c)
{
i = partion(R,b,c);
SwapSortB(R,b,i-1);
SwapSortB(R,i+1,c);
}
}
void main()
{
int r[11] = {34546,110,2,3,54,5,6,17,8,9,10};
int b = 0;
int c = 10;
int i ;
SwapSortB(r,b,c);
for(i=0;i<11;i++)
{
printf("%d,",r[i]);
}
printf("\n");
}
动态规划算法(求最优解)
动态规划算法通常用于求解某种具有最优性质的问题。在这类问题中,可能会存在许多可行解,每个可行解都对应一个值,
我们希望在这些值中找到最优解。动态规划算法与分治算法的相同点在于,他们都是将原问题分解为若干个子问题,先求解这
若干个子问题,最后将这些子问题的解合并起来得到原问题的解。不同点在于,使用动态规划算法解决的若干子问题往往不是
相互独立的。
动态规划算法能解决的问题一般具有如下的特征:
(1)分析最优解的性质,并刻画其结构特征;
(2)递归的定义最优解;
(3)以自底向上或自顶向下的记忆化方式(备忘录法)计算出最优值;
(4)根据计算最优值时得到的信息,构造问题的最优解;
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
问题描述:上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数字加起来
可以得到一个和,和最大的路径为最佳路径。求出最佳路径上的数字之和。
注意:路径上的每一步只能从一个数走到下一层和他最近的左边数和右边数。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <memory.h>
#define MaxNum 100
int D[MaxNum + 10][MaxNum + 10];
int N;
int aMaxSum[MaxNum + 10][MaxNum + 10];
int MaxSum(int x, int y)
{
if (x == N)
return D[x][y];
if (aMaxSum[x + 1][y] == -1) //
aMaxSum[x + 1][y] = MaxSum(x + 1, y);
if (aMaxSum[x + 1][y + 1] == -1)
aMaxSum[x + 1][y + 1] = MaxSum(x + 1, y + 1);
printf("aMaxSum[4][1] = %d\n", aMaxSum[4][1]);
if (aMaxSum[x + 1][y] > aMaxSum[x + 1][y + 1])
return aMaxSum[x + 1][y] + D[x][y];
return aMaxSum[x + 1][y+1] + D[x][y];
}
int main(void)
{
int i, j;
scanf("%d", &N);
memset(aMaxSum,-1,sizeof(aMaxSum));
for (i = 1; i <= N; i++)
for (j = 1; j <= i; j++)
scanf("%d", &D[i][j]);
printf("%d\n", MaxSum(1, 1));
return 0;
}
贪心算法
贪心算法是一种求最优解的一种常用方法,指所求问题的整体最优解可以通过一系列局部最优的选择即贪心选择来完成。
也就是说,不从整体最优上加以考虑,只做出某种意义上的局部最优解。贪心算法并不是对所有问题都能得到整体最优解,其
关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响到以后的状态,只与当前状态有关。
贪心算法适用的问题:贪心策略适用的前提是局部问题最优策略能导致产生全局最优解。但是实际上,贪心算法适用的情况
比较少。一般来说,对一个问题分析是否适应于贪心算法,可以先选择该问题下的几个实际实例进行分析,就可以做出判断。
贪心算法的步骤:
(1)建立数学模型来描述问题;
(2)把求解的问题分#include <iostream>
#include <math.h>
#include <algorithm>
using namespace std;
char ch[] = { "Hello,World!" };
int main()
{
for(int i = 0; ch[i] != '\0';i++)
cout << ch[i] << " ";
return 0;
}成若干个子问题;
(3)对每一个子问题求解,得到子问题的局部最优解;
(4)把子问题的局部最优解合成原问题的一个解。
#include <stdio.h>
void main()
{
int act[11][3] =
{
{1,1,4},
{2,3,5},
{3,0,6,
{4,5,7},
{6,5,9},
{7,6,10},
{8,8,11},
{9,8,12},
{10,2,13},
{10,2,13},
{11,12,13}
};
greedy(act,11);
return;
}