博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
实验报告2-求解数字金字塔(分治、备忘录、递推)+bfs实现图形面积计算
阅读量:2067 次
发布时间:2019-04-29

本文共 4743 字,大约阅读时间需要 15 分钟。

文章目录

基本概念的理解:https://www.zhoulujun.cn/html/theory/engineering/model/7307.html

数字金字塔

题目描述:

(请分别使用分治、记忆化搜索和递推三种方法完成)
观察下面的数字金字塔。写一个程序查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以从当前点走到左下方的点也可以到达右下方的点。
在上面的样例中,从13到8到26到15到24的路径产生了最大的和86。
输入
第一个行包含R(1<= R<=1000),表示行的数目。后面每行为这个数字金字塔特定行包含的整数。所有的被供应的整数是非负的且不大于100。
输出
单独的一行,包含那个可能得到的最大的和。
样例输入

5                    //数塔层数1311   812   7    266   14    15    812   7    13   24    11

样例输出:

86

深搜(Depth First Search)

深度优先搜索是一种枚举所有完整路径以遍历所有情况的搜索方法;

利用DFS算法求解出每条路径数字累加和;用一个变量记录所有可能的值中最大值,即为问题的解。

#include 
using namespace std;// 定义数字金字塔数组,ansint data[105][105], ans=0, n;/* @parm:x、y 表示数字的在金字塔中的位置,初始值位1,1表示第一个元素*/void dfs(int x, int y, int curr){
if(x==n){
ans = ans < curr ? curr : ans; return ; } // 每次在递归出口处算出最大值 dfs(x+1,y,curr+data[x+1][y]); dfs(x+1,y+1,curr+data[x+1][y+1]);}int main(){
memset(data, 0, sizeof(data)); cin >> n; for (int i=1; i<=n; i++) {
for(int j=1; j<=i; j++) {
cin >> data[i][j]; } } // 数字金字塔赋初值 dfs(1,1,data[1][1]); cout << ans << endl; return 0;}

分治法求解

分治:将原问题分解为若干个规模较小但类似于原问题的子问题(Divide),递归地求解这些子问题(Conquer),然后再合并这些子问题的解来建立原问题的解(Merge)。

对于这种写法,其函数含义为:用当前位置值data[x][y])加上正下方与右下方数字和较大值max(dfs(x+1,y),dfs(x+1,y+1)),由于一开始下方的较大数字和是未知的,所以一直递归到边界(金字塔最后一层),再递归回去即可求出最大路径数字和;

代码如下:

#include 
#include
using namespace std;/* data: 存放数字金字塔n:金字塔的层数*/int data[105][105], n;/* @param x、y : 表示元素在金字塔中的位置;初始值为1,1表示第一个元素*/int dfs(int x, int y){
if(x==n){
return data[x][y]; } return data[x][y] + max(dfs(x+1, y), dfs( x+1, y+1)); //当前数 + 下一层到n-1层的最大数字和}int main(){
cin >> n; for (int i=1; i<=n; i++) {
for(int j=1; j<=i; j++) {
cin >> data[i][j]; } } // 数字金字塔赋初值 cout << dfs(1,1) << endl; return 0;}

记忆化搜索

可以看出"分治法"求解过程存在很多重复计算,很容易想到用记忆化搜索来避免重复

代码如下:

#include 
#include
using namespace std;//备忘录算法求解数字金字塔int data[105][105]; //存放数字金字塔int n; //金字塔的层数int p[105][105]; //备忘录/* @param x、y : 表示元素在金字塔中的位置;初始值为1,1表示第一个元素*/int dfs(int x, int y){
if(p[x][y] !=-1){
return p[x][y]; //如果备忘录里面有,直接返回 } if(x==n){
return data[x][y]; } p[x][y] = data[x][y] + max(dfs(x+1, y), dfs( x+1, y+1)); return p[x][y]; //当前数 + 下一层到n-1层的最大数字和}int main(){
memset(p, -1, sizeof(p)); //初始化备忘录 cin >> n; for (int i=1; i<=n; i++) {
for(int j=1; j<=i; j++) {
cin >> data[i][j]; } } // 数组赋值 cout << dfs(1,1) << endl; return 0;}

递推

自下而上,从已知到未知;

#include 
#include
#define MAX 105using namespace std;// 递推求解数字金字塔/*51311 812 7 266 14 15 812 7 13 24 11*/int data[MAX][MAX];int main(){
int n; //5 cin >> n; for(int i=1; i<=n; i++){
for(int j=1; j<=i; j++){
cin >> data[i][j]; } } for(int i=n-1; i>=1; i--){
for(int j=1; j<=i;j++){
data[i][j] = max(data[i+1][j],data[i+1][j+1]) + data[i][j]; // 自底向上 } } cout << data[1][1] <

递推参考资料:

https://blog.csdn.net/weixin_45592404/article/details/104319004


bfs实现图形面积计算

题目描述:

编程计算由“"号围成的下列图形的面积。面积计算方法是统计号所围成的闭合曲线中水平线和垂直线交点的数目。如下图所示,在10*10的二维数组中,有"*"围住了15个点,因此面积为15。输入如下:

0  0  0  0  0  0  0  0  0  00  0  0  0  *  *  *  0  0  00  0  0  0  *  0  0  *  0  00  0  0  0  0  *  0  0  *  00  0  *  0  0  0  *  0  *  00  *  0  *  0  *  0  0  *  00  *  0  0  *  *  0  *  *  00  0  *  0  0  0  0  *  0  00  0  0  *  *  *  *  *  0  00  0  0  0  0  0  0  0  0  0

思路:用bfs得到一个bool数组,它记录入过队列的’0’(这些元素是被访问过的),而被"*"围起来的0是未被访问的;根据这个特点产生如下判别条件:如果数组元素是’0’并且这个元素没有被访问过,该元素即为面积的一部分

代码实现:

#include 
#include
using namespace std;struct node{
int x,y; // 位置(x,y)} Node;// const int maxn = 20;int n = 10; //图形sizechar matrix[10][10];bool inq[10][10]={
false}; //记录位置(x,y)是否已入过队int dir[4][2] = {
{
-1,0},{
1,0},{
0,-1},{
0,1}}; // 增量数组// 判断坐标(x,y)是否需要被访问,需要返回true,否则返回falsebool judge(int x, int y){
// 越界返回flase if(x>=n || x<0 || y>=n || y<0 ) return false; // 如果(x,y)已入过队列,或(当前位置为'*'),返回false if(inq[x][y] || matrix[x][y]=='*') return false; //以上都不满足返回true return true;} void bfs(int x, int y){
queue
Q; //定义队列 Node.x = x, Node.y = y; // 当前节点的坐标为(x,y) Q.push(Node); // 将节点Node入队 inq[x][y] = true; while(!Q.empty()){
node top = Q.front(); //取出队首元素 Q.pop(); // 队首元素出队 // 循环4次,得到4个相邻位置 for(int i=0; i<4; i++){
int newX = top.x + dir[i][0]; int newY = top.y + dir[i][1]; // 如果新位置(newX,newY)需要访问 if(judge(newX, newY)){
Node.x = newX; Node.y = newY; Q.push(Node); // 将节点加入队列 inq[newX][newY] = true; // 设置位置(newX,newY)已经入过队列 } } }}int main(){
for (int i=0; i
> matrix[i][j]; //初始化图形,char型数组录入的是字符'0' } } int count = 0; // 面积 bfs(0,0); for(int i=0; i

bfs学习参考资料:

  • https://www.bilibili.com/video/BV1AE411a7Wp?from=search&seid=16783551617652526193
  • 《算法笔记》

总结

通过本次实验,

  • 对分治、记忆化搜索、递推有了一定了解;
  • 学习了广度优先搜索,C++STL中queue的使用;
你可能感兴趣的文章
PHPstudy中遇到的坑No input file specified,以及传到linux环境下遇到的坑,模板文件不存在
查看>>
TP5.1事务操作和TP5事务回滚操作多表
查看>>
composer install或composer update 或 composer require phpoffice/phpexcel 失败解决办法
查看>>
TP5.1项目从windows的Apache服务迁移到linux的Nginx服务需要注意几点。
查看>>
win10安装软件 打开时报错 找不到 msvcp120.dll
查看>>
PHPunit+Xdebug代码覆盖率以及遇到的问题汇总
查看>>
PHPUnit安装及使用
查看>>
PHP项目用xhprof性能分析(安装及应用实例)
查看>>
composer安装YII
查看>>
Sublime text3快捷键演示
查看>>
sublime text3 快捷键修改
查看>>
计算机底层是什么东西?
查看>>
关于PHP几点建议
查看>>
硬盘的接口、协议
查看>>
安装系统之一 U盘启动盘制作
查看>>
安装系统之二 U盘启动盘制作---UEFI版
查看>>
安装系统之四 U盘装GHOST XP教程
查看>>
安装系统之五 U盘装原版XP教程
查看>>
安装系统之六 U盘装GHOST WIN7教程
查看>>
安装系统之八 U盘装GHOST WIN8教程
查看>>