博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
DFS回溯-函数递归-xiaoz triangles
阅读量:5896 次
发布时间:2019-06-19

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

题目:小z 的三角形

★实验任务

三角形的第1 行有n 个由“+”和”-“组成的符号,以后每行符
号比上行少1 个,2 个同号下面是”+“,2 个异号下面是”-“ 。
计算有多少个不同的符号三角形,使其所含”+“ 的个数是”-“ 的
个数的一半。n=7 时的1 个符号三角形如下:

+ + - + - + ++ - - - - +- + + + -- + + -- + -- -+

★数据输入

第一行为一个整数N(0<N<=12),表示符合三角形的大小。
★数据输出
输出所有满足题意的图案和总个数(输出的图案按图案中第一行
的字典序排序。例如:n=2 时,按++,+-,-+,--的顺序,因为第一行
为++的图案不符合题意,故样例只输出了+-,-+,--)符号之间以空格
隔开。
输入示例输出示例

2 + ---+---+3Hint可以枚举第一行’+’和’-’的情况来补充完整整个三角形

此题难点在于如何对第一行进行遍历,判断和实现三角形的输出相对比较简单,可以使用异或的方法来做。

这里使用深度优先搜索的函数递归调用来对第一行的每一种情况进行分析进而实现回溯,在每一个节点的位置上,都有+-两种情况,利用递归进行搜索判断。这里参考了汉森和昭锡的代码。
代码1:

#include 
#include
#include
#include
using namespace std;int f[20][20];int n;int ans=0;void done()//done()函数执行判断和输出符合要求的三角形{ int i,j; for(i=2;i<=n;i++) { for(j=1;j<=n-i+1;j++) { if(f[i-1][j]!=f[i-1][j+1])f[i][j]=2; else f[i][j]=1; } } int cnt1=0,cnt2=0; for(i=1;i<=n;i++) { for(j=1;j<=n-i+1;j++) { if(f[i][j]==1)cnt1++; else cnt2++; } } //cout<
<<" : "<
<
n) { done(); return ; }//遇到终点执行done()部分 else { f[1][t]=1; t++; work(t);//此时该节点为'+' t--; f[1][t]=2; t++; work(t);//此时该节点为'-' }//实现DFS算法函数递归和判断的部分}int main(){ cin>>n; work(1); cout<

代码1相对较好理解,整串代码的核心是work()函数:

void work(int t){    //cout<<1<
n) { done(); return ; }//遇到终点执行done()部分 else { f[1][t]=1; t++; work(t);//此时该节点为'+' t--;//回到位置,归位 f[1][t]=2; t++; work(t);//此时该节点为'-' }//实现DFS算法函数递归和判断的部分}

work()函数分成两个部分:

第一个部分

if(t>n)    {    done();    return ;    }//遇到终点执行done()部分

此时无法继续向下搜索,执行done()部分。

第二个部分

else    {//第一个小节        f[1][t]=1;        t++;        work(t);//此时该节点为'+'//第二个小节    t--;//回到位置,归位//第三个小节         f[1][t]=2;        t++;        work(t);//此时该节点为'-'    }//实现DFS算法函数递归和判断的部分

虽说只有寥寥几行代码,但确实难以理解。

第二个部分可以分成三个小节:第一个小节代表此时停留的这个节点的状态是+,然后进行向下遍历的操作。第三个小节与第一个小节类似,代表此时停留的这个节点的状态是-。第二个小节t--代表归位(在第一个小节遍历它的所有情况结束以后进行了一次多余的t++操作),从而进行接下来的第三个小节的遍历操作。

大概的意思是,此时该节点的状态如果是+,进行DFS搜索接下来(当这个节点状态是+时)所有的情况,然后返回这个节点,再看这个节点此时的状态如果是-,进行DFS搜索接下来(当这个节点状态是-时)所有的情况,搜索结束以后,这个节点不管状态是+,或是-,它接下来所有的可能性都已经搜索过一遍了。

然后返回这个节点之前的节点,再进行判断。从最末尾开始,一直到最初的起点。

885822-20160317205133943-1618504813.png

可以想象成一棵树,从它的果实返回到它的一个枝节,从它的枝节返回到树的主干。再从主干返回到根。

大家可以通过草稿纸上的模拟进行理解。

代码2:

#include
const int MAX_M =15;const int MAX_N =15;int ans[MAX_M][MAX_N];int cnt = 0;void dfs(int n,int i){ if(i

代码2与代码1的区别在于,它使用了异或来补充三角形。而且把条件判断和输出三角形放在了同一个函数中。

与本题类似的题目:

参考资料:

2016/3/17

转载地址:http://ckasx.baihongyu.com/

你可能感兴趣的文章
blog addr
查看>>
如何选择 Web 前端模板引擎?
查看>>
VMware 上Clone Ubuntu虚拟机后找不到eth0
查看>>
由毫秒(ms)转换为日期和时间的格式(简单易用)
查看>>
一个女生对BootStrap的感情
查看>>
VMware VIX API使用教程
查看>>
The Shared folder with you
查看>>
Servlet+JSP+MySQL实现用户管理模块之七、实现用户信息更新和重置密码
查看>>
动态规划本质理解:01背包问题
查看>>
微软官方32位版Windows Server 2008下载
查看>>
简单纪要:java 从txt文本中 读取数据
查看>>
Nginx+FastCGI运行原理
查看>>
笔记——搭建简易NFS服务
查看>>
虚拟磁盘恢复虚拟机
查看>>
zabbix通过自定义脚本监控nginx,php-fpm和mysql占用内存数和进程的个数
查看>>
车载3G /WIFI设备,让汽车搭上移动互联网
查看>>
day1
查看>>
GNU GRUB version 0.97 (630K lower /2053824K upper memory)
查看>>
urllib与urllib2的学习总结
查看>>
如何配置Qt使用VS2010进行开发-转
查看>>