问题描述:
如下图是由14个“+”和14个“-”组成的符号三角形, 2个同号下面都是“+”,2个异号下面都是“-”。
- + + - + + +
- + - - + +
- - + - +
+ - - -
- + +
- +
-
在一般情况下,符号三角形的第一行有n个符号, 符号三角形问题要求对于给定的n,
计算有多少个不同的符号三角形,使其所含的“+”和“-”的个数相同。
解题思路:
1、不断改变第一行每个符号,搜索符合条件的解,可以使用递归回溯
为了便于运算,设+ 为0,- 为1,这样可以使用异或运算符表示符号三角形的关系
++为+即0^0=0, --为+即1^1=0, +-为-即0^1=1, -+为-即1^0=1;
2、因为两种符号个数相同,可以对题解树剪枝,
当所有符号总数为奇数时无解,当某种符号超过总数一半时无解
#include<iostream>
#include<cstring>
using namespace std;
int map[1100][1100];
int n,ans,sum,cnt;//cnt用于统计-号个数
//"+" 是0,”-“是1
void dfs(int step,int cnt)//第一行所在的列数
{
if(step>n)
{
ans++;
for(int i=1;i<=n;i++)
{
cout<<string(i-1,' ');
for(int j=1;j<=n-i+1;j++)
{
if(map[i][j]==0)cout<<"+";else cout<<"-";
cout<<" ";
}
cout<<endl;
}
return ;
}
for(int i=0;i<=1;i++)
{
int tmp=0;//统计增加的加号的个数
map[1][step]=i;tmp+=i;
for(int j=2;j<=step;j++)//枚举添加一个符号增加的行标号
{
map[j][step+1-j]=map[j-1][step+1-j]^map[j-1][step+2-j];
tmp+=map[j][step+1-j];
}
if(cnt+tmp<=sum/2&&(step*(step+1)/2-cnt-tmp<=sum/2))dfs(step+1,cnt+tmp);
}
}
int main()
{
cin>>n;sum=(n*(n+1))>>1;
if(sum&1){cout<<1;return 0;}
dfs(1,0);
cout<<ans<<endl;
}
#include<iostream>
#include<cstring>
using namespace std;
int p[1001][1001];
int sum;
int n;
int half;
int cnt;
void dfs(int t)
{
if((cnt>half)|| ((t*(t-1)/2-cnt)>half) )return;
if(t>n)
{
for(int i=1;i<=n;i++)
{
for(int j=n+1-i;j>=1;j--)
if(p[i][j]==1)cout<<"+ ";
else cout<<"- ";
cout<<endl;
}
cout<<endl;
sum++;
return;
}
for(int i=0;i<2;i++)
{
p[1][t]=i;
cnt+=i;
for(int j=2;j<=t;j++)
{
p[j][t-j+1]=1-p[j-1][t-j+1]^p[j-1][t-j+2];
cnt+=p[j][t-j+1];
}
dfs(t+1);
for(int j=2;j<=t;j++)
{
cnt-=p[j][t-j+1];
}
cnt-=i;
}
}
int main()
{
cin>>n;
if((n*(n+1)/2)&1)
{
cout<<sum<<endl;return 0;
}
half=(n*(n+1))/4;
dfs(1);
cout<<sum<<endl;
return 0;
}