幸运三角形
时间限制:1000 ms | 内存限制:65535 KB
难度:3
- 描述
-
话说有这么一个图形,只有两种符号组成(‘+’或者‘-’),图形的最上层有n个符号,往下个数依次减一,形成倒置的金字塔形状,除第一层外(第一层为所有可能情况),每层形状都由上层决定,相邻的符号相同,则下层的符号为‘+’,反之,为‘-’;如下图所示(n = 3 时的两种情况):
如果图中的两种符号个数相同,那这个三角形就是幸运三角形,如上图中的图(2).
- 输入
- 有多组测试数据(少于20组)。
每行含一个整数n(0<n<20)。 - 输出
- 输出相应的幸运三角形个数。
- 样例输入
-
3 4
- 样例输出
-
4 6
代码一: TLE1 #include <cstdio> 2 #include <iostream> 3 4 using namespace std; 5 int a[25]; 6 int n, cnt; 7 8 bool judge() 9 { 10 int t0, t1; 11 t0 = t1 = 0; 12 for(int end = n; end >= 1; --end) 13 { 14 for(int i = 1; i <= end; ++i) 15 { 16 if(a[i] == 1) 17 ++t1; 18 else 19 ++t0; 20 if(t1 > ((n+1)*n>>1) || t1 > ((n+1)*n>>1)) //剪枝 21 return false; 22 if(i > 1) 23 { 24 if(a[i] == a[i-1]) 25 a[i-1] = 1; 26 else 27 a[i-1] = 0; 28 } 29 } 30 } 31 if(t0 == t1) 32 return true; 33 return false; 34 } 35 36 void DFS(int cur) 37 { 38 if(cur > n) 39 { 40 if(judge()) 41 ++cnt; 42 return; 43 } 44 a[cur] = 1; 45 DFS(cur+1); 46 a[cur] = 0; 47 DFS(cur+1); 48 } 49 50 int main() 51 { 52 while(scanf("%d", &n)) 53 { 54 if(((n+1)*n>>1) & 1) 55 { 56 printf("0\n"); 57 continue; 58 } 59 cnt = 0; 60 DFS(1); 61 printf("%d\n", cnt); 62 } 63 return 0; 64 }
代码二:打表-----AC
1 #include <cstdio> 2 #include <iostream> 3 4 using namespace std; 5 6 int main() 7 { 8 int ans[21] = {0,0,0,4,6,0,0,12,40,0,0,171,410,0,0,1896,5160,0,0,32757,59984}; 9 int n; 10 while(~scanf("%d", &n)) 11 { 12 printf("%d\n", ans[n]); 13 } 14 return 0; 15 }
代码三:----copy最优代码(边计算边回溯,避免了重复计算,很给力啊)
1 #include"iostream" 2 #include<cstring> 3 #include<stdio.h> 4 #include<time.h> 5 using namespace std; 6 typedef unsigned char uchar; 7 8 //char cc[2]={'+','-'}; //便于输出 9 int n, //第一行符号总数 10 half, //全部符号总数一半 11 counter; //1计数,即 '-' 号计数 12 13 char **p; //符号存储空间 14 long sum; //符合条件的三角形计数 15 16 //t,第一行第 t个符号 17 void Backtrace(int t) 18 { 19 int i, j; 20 21 if( t > n ) 22 sum++; 23 else 24 { 25 for(i=0; i<2; ++i) //只取 0('+') 或者 1('-') 26 { 27 p[1][t] = i; //第一行第 t个符号 28 counter += i; //'-'号统计 29 for(j=2; j<=t; ++j) //当第一行符号 >=2时,可以运算出下面行的某些符号(第一行有几个数就可以相应往下计算几行,每次计算过的就不用重复计算) 30 { 31 p[j][t-j+1] = p[j-1][t-j+1]^p[j-1][t-j+2];//通过异或运算下行符号 32 counter += p[j][t-j+1]; 33 } 34 if( (counter <= half) && ( t*(t+1)/2 - counter <= half) )//若符号统计未超过半数,并且另一种符号也未超过半数 35 Backtrace(t+1); //在第一行增加下一个符号 36 //回溯,判断另一种符号情况 37 for(j=2; j<=t; ++j) 38 counter -= p[j][t-j+1]; 39 counter -= i; 40 } 41 } 42 } 43 44 int main() 45 { 46 while(scanf("%d", &n) != EOF) 47 { 48 counter = 0; 49 sum = 0; 50 half = n*(n+1)/2; 51 52 if( half%2 == 0 )//总数须为偶数,若为奇数则无解 53 { 54 half /= 2; 55 p = new char *[n+1]; 56 for(int i=0; i<=n; ++i) 57 { 58 p[i] = new char[n+1]; 59 memset(p[i], 0, sizeof(char)*(n+1)); 60 } 61 Backtrace(1); 62 } 63 printf("%d\n", sum); 64 } 65 return 0; 66 }