题目描述
符号三角形的 第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会超时,直接自己写好数组,根据输入直接从数组中读取就好啦~