经典算法问题
【1】猴子爬山问题——递推算法
猴子每次爬 1 级或 2 级台阶,有多少种不同的方法爬20级能到达楼顶呢?
(1)给出爬梯子问题的状态转换方程
解:由题意得:
f(20) = f(19) + f(18)
f(19) = f(18) + f(17)
…
f(2) = 2
f(1) = 1
所以状态转换方程为:f(n) = f(n-1) + f(n-2 )
(2)给出基于状态转换方程的递推实现
int c(int n) {
int i;
if (n==1||n==2){
return n;
}
for(i=2;i<n;i++){
f[i]=f[i-1]+f[i-2];
}
return f[n-1];
}
程序源代码:
#include <stdio.h>
#include <stdlib.h>
int f[20];
int main(){
int i,j;
f[0] = 1;
f[1] = 2;
for(i=0;i<20;i++){
if(i%5==0)
printf("\n");
printf("%4d ",c(i));
}
printf("\n猴子爬到第%d阶有%d种",i,c(i));
}
int c(int n) {
int i;
if (n==1||n==2)
return n;
for(i=2;i<n;i++)
f[i]=f[i-1]+f[i-2];
return f[n-1];
}
程序运行截图:
【2】N皇后问题——回溯算法
设计回溯算法,解决四皇后问题(在4×4的方格棋盘上放置4个皇后使它们互不攻击),要求能输出回溯的过程。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main() {
int g,k,j,x,a[5]= {0,1,0,0,0},i=1,s=0;
while (1) {
g=1;
for(k=i-1; k>=1; k--) {
x=abs(a[i]-a[k]);
if(x==0 || x==i-k) g=0;
}
if(i==4 && g==1) {
for(j=1; j<=4; j++)
printf("%4d",a[j]);
printf("\n");
s++;
}
if(i<4 && g==1) {
i++;
a[i]=1;
continue;
}
while(a[i]==4 && i>1)
i--;
if(i==1&&a[i]==4)
break;
else
a[i]=a[i]+1;
}
printf("\n 共%d个解.\n",s);
}
运行程序结果:
【3】最大路径和问题——动态规划算法
给定一个矩阵m如下图,从左上角开始每次只能向右走或者向下走,最后达到右下角的位置,路径中所有数字累加起来就是路径和,求出所有路径的最大路径和。
源代码:
#include <stdio.h>
#include <stdlib.h>
int main() {
int a[4][4]= {1,3,5,9,
8,1,3,4,
5,0,6,1,
8,8,4,0};
int dp[4][4]; //存放决策表(最短路径状态矩阵)
int i,j;
//边界条件问题需要考虑到
dp[0][0]=a[0][0]; //左上角(i==0&&j=0)
for (j=1; j<4; j++)
dp[0][j]=a[0][j]+dp[0][j-1];//初始化上沿线(i==0&&j!=0)
for (i=1; i<4; i++)
dp[i][0]=a[i][0]+dp[i-1][0];//初始化左沿线(i!=0&&j==0)
for (i=1; i<4; i++) //遍历计算到达各点的最短路径值
for (j=1; j<4; j++)
dp[i][j]=a[i][j]+(dp[i-1][j]>dp[i][j-1]?dp[i-1][j]:dp[i][j-1]);
for (i=0; i<4; i++) {
for (j=0; j<4; j++)
printf("%4d",dp[i][j]);
printf("\n");
}
}
程序运行截图:
【4】韩信点兵问题——枚举算法
韩信先令士兵从1-3报数,结果最后一个士兵报2;从1-5报数,最后一个士兵报3,;从1-7报数,最后一个士兵报4.用C语言编写程序计算士兵总数至少有多少人?
源程序:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i=1;
while(i<1000){
if(i%3==2&&i%5==3&&i%7==4)
printf("%d\n",i);
i++;
}
return 0;
}
程序运行结果: