符号三角形

本文探讨了一种特殊的符号三角形,其每一行由“+”和”-“组成,通过回溯算法和深度优先搜索算法计算符合特定条件的三角形数量。在n=7的情况下,展示了具体的三角形实例。由于直接算法在某些情况下会超时,文章还介绍了如何使用打表法预先计算结果,以提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

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

input

每行1个正整数n <=24,n=0退出.

output

n和符号三角形的个数.

sample input

15
16
19
20
0

sample output

15 1896
16 5160
19 32757
20 59984

这个题用到了回溯算法和深搜算法,但是放代码会超时,所以打表提交
代码如下:

#include<iostream>
using namespace std;
int n=0,half=0,ans=0;
int num=0;//num表示1的数目 
int tri[30][30];//整形数组存放三角形,用0表示'+',用1表示'-' 
void dfs(int step)//step表示当前的层数
{
	if((num>half) || (step*(step-1)/2-num>half))//如果当前0的数目或者1的数目已经超过规定数目,则剪枝 
		return ;
	if(step>n)//如果已经达到要求的层数而且1的数目为规定数目,符合条件,答案+1 
	{
		ans++;
		return ;
	}
		for(int i=0;i<=1;i++)//因为二维数组中可能的元素只有0,1两种, 
	{
		tri[1][step]=i;//确定下第一行元素,则后面的都可以推出来,这里在前面的基础上只需要再加上第step个元素就可以, 
		for(int j=2;j<=step;j++)//针对当前确定的第一行元素退出后面的,从第二层直到第step层 
		{
			tri[j][step-j+1]=tri[j-1][step-j+1]^tri[j-1][step-j+2];//如果上一层两个元素相同,则该元素为0,运算符'^'表示二进制按位异或  
			num=num+tri[j][step-j+1];//计算出当前1的数目为 
		}//当前step层的符号三角形已经构建好 
		num=num+i;
		dfs(step+1);//对下一层进行递归 
		for(int j=2;j<=step;j++)//回溯的时候要复原 
		{
			num=num-tri[j][step-j+1];
		}
		num=num-i;
	}
}
int main ()
{
	while(cin>>n,n!=0)//输入要求的层数 
	{
		ans=0;
		num=0;
		cout<<n<<" ";
		int sum=n*(n+1)/2;//该层数三角形共有sum个字符 
		
		if(sum%2!=0)//如果sum为奇数,不存在题目要求的符号三角形 
			cout<<"0"<<endl;
		else//否则,进行神搜 
		{
			half=sum/2;
			dfs(1);//从第一行第一个元素开始,0表示记录当前符号'-'的数目 
			cout<<ans<<endl; 
		}
	}
	return 0;
}

打表代码:

#include<iostream>
#include<cstdio>
using namespace std;
int main ()
{
	int n;
	int a[25]={0,0,0,4,6,0,0,12,40,0,0,171,410,0,0,1896,5160,0,0,32757,59984,0,0,431095,822229};
	while(cin>>n,n!=0)
	{
		cout<<n<<" "<<a[n]<<endl;
	}
	return 0;
}
  

这个题上来我是不会做的,后来跟着大佬的博客看,终于写出来了,提交之后发现又超时,然后一搜发现还有“打表”这种操作,先在电脑上把结果运行出来,因为数据只是到24,如果提交在线oj会超时,直接自己写好数组,根据输入直接从数组中读取就好啦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值