Problem Description
符号三角形的 第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
解题思路:
“2个同号下面是‘+’,2个异 号下面是‘-’”,类似于位运算中的异或。
直接用‘+’,‘-’来进行计算,多少有点麻烦,所以选择用 0 代表 ‘+’ , 用 1 代表 ‘-’ 。
本题主要涉及的内容主要是 位运算相关知识 ,讲解 位运算。
代码:
//位运算
//两位相同则为 0 , 不同为 1。
//n <= 24 , 打表
#include <cstdio>
using namespace std;
//求取过程
int ans[30] ;
int a[30];
int main(){
int n , i , j , k ;
for(i = 1 ; i <=24 ; i ++){ // n 总共有 24 种情况
//遍历 n = 1 ~ 24 的各种情况 , 其中每种情况下也分为2^n中不同的取值情况
a[1] = (1 << i) - 1; //最大值
while(a[1] >= 0){ //依次遍历 2^n种情况
for( j = 2 ; j <= i ; j ++){ //求出 n-1 到 1 层的取值情况
a[j] = 0;
for(k = 0 ; k < i - j + 1 ; k ++) // i-j+1表示当前该层的数字的个数
// k 表示当前求取的数所在的位
a[j] = a[j] | ( (a[j-1]>>k)&1 ^ (a[j-1]>>k+1)&1 ) << k; //从后向前求取
}
int ans1 = 0 , ans2 = 0;
for(j = 1 ; j <= i ; j ++){ //统计个数
for(k = 0 ; k < i - j + 1 ; k ++){
if((a[j] >> k)&1) //为 0;
ans1 ++;
else
ans2 ++;
}
}
if(ans1 == ans2)
ans[i] ++;
a[1] --;
}
printf("%d ",ans[i]);
}
return 0;
}
运行结果:
注:直接提交上述代码肯定是会超时的 , 所以直接把上述代码的结果保存在一个结果数组里面,以下为AC代码 。
AC代码
int ans[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};
int main(){
int n;
while(scanf("%d" , &n) != EOF && n){
printf("%d %d\n",n , ans[n]);
}
return 0;
}