题目:小z 的三角形

★实验任务

三角形的第1 行有n 个由“+”和”-“组成的符号,以后每行符

号比上行少1 个,2 个同号下面是”+“,2 个异号下面是”-“ 。

计算有多少个不同的符号三角形,使其所含”+“ 的个数是”-“ 的

个数的一半。n=7 时的1 个符号三角形如下:

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

★数据输入

第一行为一个整数N(0<N<=12),表示符合三角形的大小。

★数据输出

输出所有满足题意的图案和总个数(输出的图案按图案中第一行

的字典序排序。例如:n=2 时,按++,+-,-+,--的顺序,因为第一行

为++的图案不符合题意,故样例只输出了+-,-+,--)符号之间以空格

隔开。

输入示例输出示例

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

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

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

代码1:

#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
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<<cnt1<<" : "<<cnt2<<endl;
if(2*cnt1==cnt2)ans++;
else return ; for(i=1;i<=n;i++)
{
for(j=1;j<=n-i+1;j++)
{
if(f[i][j]==1)cout<<"+ ";
else cout<<"- ";
}
cout<<endl;
}
return ; }
void work(int t)
{
//cout<<1<<endl;
if(t>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<<ans; return 0;
}

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

void work(int t)
{
//cout<<1<<endl;
if(t>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搜索接下来(当这个节点状态是-时)所有的情况,搜索结束以后,这个节点不管状态是+,或是-,它接下来所有的可能性都已经搜索过一遍了。

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

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

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

代码2:

#include<stdio.h>
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<n+1)
{
ans[1][i]=0; dfs(n,i+1);
}
else
{
int j,k;
int sum1=0,sum2=0; for(j=2;j<n+1;j++)
{
for(k=1;k<n+2-j;k++)
{
ans[j][k]=ans[j-1][k]^ans[j-1][k+1];//使用异或
}
} for(j=1;j<n+1;j++)
{
for(k=1;k<n+2-j;k++)
{
if(ans[j][k])
sum1++;
else
sum2++;
}
} if(sum1==sum2*2)
{
cnt++;
for(j=1;j<n+1;j++)
{
for(k=1;k<n+2-j;k++)
{
if(k==1)
{
if(ans[j][k])
printf("-");
else
printf("+");
}
else if(ans[j][k])
printf(" -");
else
printf(" +");
}
printf("\n");
}
}
return;
} ans[1][i] = 1;
dfs(n,i+1);
return ;
} int main()
{
int N; scanf("%d",&N); dfs(N,1); printf("%d\n",cnt); return 0;
}

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

与本题类似的题目:hdoj2510

参考资料:zzy19961112

2016/3/17

DFS回溯-函数递归-xiaoz triangles的更多相关文章

  1. 素数环(dfs+回溯)

    题目描述: 输入正整数n,把整数1,2...n组成一个环,使得相邻两个数和为素数.输出时从整数1开始逆时针排列并且不能重复: 例样输入: 6 例样输出: 1 4 3 2 5 6 1 6 5 2 3 4 ...

  2. 八皇后,回溯与递归(Python实现)

    八皇后问题是十九世纪著名的数学家高斯1850年提出 .以下为python语句的八皇后代码,摘自<Python基础教程>,代码相对于其他语言,来得短小且一次性可以打印出92种结果.同时可以扩 ...

  3. python 函数递归与匿名函数

    1.什么是函数递归? 函数递归调用(是一种特殊的嵌套调用):在调用的函数过程中,又直接或者间接的调用了该函数本身 递归必须要有两个明确的阶段: 递推:一层一层递归调用下去,强调每进入下一层递归问题的规 ...

  4. 剪格子---(dfs回溯)

    如图p1.jpg所示,3 x 3 的格子中填写了一些整数. 我们沿着图中的红色线剪开,得到两个部分,每个部分的数字和都是60. 本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以 ...

  5. Learning-Python【14】:匿名函数与函数递归

    一.什么是匿名函数 匿名函数就是没有名字的函数,又叫lambda表达式.用于一些简单的需要用函数去解决的问题,特点是只能在定义时使用一次,且函数体只有一行 匿名函数的定义就相当于只产生一个变量的值,而 ...

  6. python之旅:三元表达式、列表推导式、生成器表达式、函数递归、匿名函数、内置函数

    三元表达式 #以下是比较大小,并返回值 def max2(x,y): if x > y: return x else: return y res=max2(10,11) print(res) # ...

  7. python 之 函数 面向过程 三元表达式 函数递归

    5.11 面向过程编程思想 核心是'过程'二字,过程即解决问题的步骤,即先干什么,再干什么........ 基于面向过程编写程序就好比在设计一条流水线,是一种机械式的思维方式. 总结优缺点: 优点:复 ...

  8. python_函数递归

    函数递归 函数递归:函数的递归调用,即在函数调用的过程中,又直接或间接地调用了函数本身 # import sys # print(sys.getrecursionlimit()) # sys.setr ...

  9. Python 函数递归-三元表达式-列表生成式-字典生成式-匿名函数-内置函数

    上节课复习: 1. 无参装饰器 def 装饰器名字(func): def wrapper(*args,**kwargs): res = func(*args,**kwargs) return res ...

随机推荐

  1. 002-Spring Cloud 功能简介

    一.主要功能 分布式/版本化配置.服务注册与发现.路由.服务间调用.负载均衡.断路器.分布式消息传递 1.云本地应用[Cloud Native Applications] Spring Cloud C ...

  2. 远程开关机神器Wake On LAN,免费有中文版

    https://wol.aquilatech.com/ Wake On Lan 又名 aquilaWOL,这是一款免费且开源的图形界面 WOL 软件,有繁体中文界面,可以管理多台电脑和网络设备,支持批 ...

  3. 优化Ubuntu 16.04系统的几件事

    安装完Ubuntu 16.04后,要更换为国内的软件源: sudo gedit /etc/apt/sources.list #用文本编辑器打开源列表 在文件开头添加下面的阿里云的软件源: deb ht ...

  4. ab压力测试遭遇apr_socket_recv: Connection reset by peer (104) 怎么办

    ab -r  -c 2000 -n 200000  www.baidu.com 其实只要加上-r就可以了.但是为什么呢?ab --help就知道了 当Socket接收到错误的时候不退出,就是这句.事实 ...

  5. [LeetCode] 182. Duplicate Emails_Easy tag: SQL

    Write a SQL query to find all duplicate emails in a table named Person. +----+---------+ | Id | Emai ...

  6. SVN 取消版本控制并添加至忽略列表

    忽略已经版本控制的文件忽略文件和目录 起因: 由于项目中的IDE Jdeveloper在某些指定目录下面会生成server.xml以及common文件夹,且包含一个名为bc4j.xcfg的文件,每次当 ...

  7. amaze ui实现下拉列表

    对amaze ui ,只能说很好,很适合开发者使用,然后省略一万字. 今天记录下下拉列表的实现. 关于调用,这里不赘述了, 直接记录代码: <ul class="am-dropdown ...

  8. eclipse工具maven项目打包文件不是最新修改的

    1.问题描述:maven项目,完成一些功能开发后,在进行打包更新服务器系统时,本地eclipse工具对文件打成jar包操作,更新到服务器上没有修改的效果,包括打包整个工程为一个war包,也是有同样问题 ...

  9. python3.4学习笔记(一) 基本语法 python3不向下兼容,有些语法跟python2.x不一样

    python3.4学习笔记(一) 基本语法 python3不向下兼容,有些语法跟python2.x不一样,IDLE shell编辑器,快捷键:ALT+p,上一个历史输入内容,ALT+n 下一个历史输入 ...

  10. apache中的https设置基于阿里云免费ssl服务

    环境是:debian7+apache2.2+阿里云免费ssl服务,站点以前的http已经在运行了, 1.开通阿里云免费SSL&DNS解析配置 购买位置:打开阿里云找到“产品”-“安全”-“CA ...