幸运三角形

时间限制:1000 ms  |  内存限制:65535 KB
难度:3
 
描述

        话说有这么一个图形,只有两种符号组成(‘+’或者‘-’),图形的最上层有n个符号,往下个数依次减一,形成倒置的金字塔形状,除第一层外(第一层为所有可能情况),每层形状都由上层决定,相邻的符号相同,则下层的符号为‘+’,反之,为‘-’;如下图所示(n = 3 时的两种情况):

                                           

如果图中的两种符号个数相同,那这个三角形就是幸运三角形,如上图中的图(2).

 
输入
有多组测试数据(少于20组)。
每行含一个整数n(0<n<20)。
输出
输出相应的幸运三角形个数。
样例输入
3
4
样例输出
4
6


代码一:  TLE 
 1 #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 }
View Code

代码二:打表-----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 } 
View Code

 

代码三:----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 }         
View Code

 

 

 

 

posted on 2013-06-16 11:43  可笑痴狂  阅读(836)  评论(0)    收藏  举报