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

如果图中的两种符号个数相同,那这个三角形就是幸运三角形,如上图中的图(2).
3 4
4 6
/*#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int n, cnt;
int a[25];
int check()//每次总是觉得这个check函数是最难得
{
int i, j, t1, t0;
t1 = 0;
t0 = 0;
for(j = n - 1; j >= 0; j--)//外层循环是有几层,即循环的n次
{
for(i = 0; i <= j; i++)//里层循环式一层有几个字符,即有j个
{
if(a[i] == 1)//计数是+还是-
t1++;
else
t0++;
if(i > 0)//因为是用的一维数组存的,所以这里的主要作用是把这个一维数组变成下一层所需要的样式
{
if(a[i] == a[i - 1])//符号相同则是+
a[i - 1] = 1;
else//否则是-
a[i - 1] = 0;
}
}
}
if(t1 == t0)
return 1;
return 0;
}
void dfs(int x)
{
if(x == n)
{
if(check() == 1)
cnt++;
return ;//开始把return放在if里面了一直出不来结果,真是笨笨的脑袋
}
a[x] = 1;//这里并没有往常一样有if判断了,而是直接深搜了
dfs(x + 1);
a[x] = 0;//这里回溯回来的时候继续深搜下去,思路还是比较清晰的
dfs(x + 1);
}
int main()
{
while(scanf("%d", &n) != EOF)
{
cnt = 0;
dfs(0);
printf("%d\n", cnt);
}
return 0;
}
*/ 打表
#include <stdio.h>
int a[21] = {0,0,0,4,6,0,0,12,40,0,0,171,410,0,0,1896,5160,0,0,32757};//打表最好不要用for循环
int main()
{
int n;
while(scanf("%d", &n) != EOF)
{
printf("%d\n", a[n]);
}
return 0;
}
OJ平台最优代码:
#include"iostream"
#include<cstring>
#include<stdio.h>
#include<time.h>
using namespace std;
typedef unsigned char uchar;
char cc[2]={‘+‘,‘-‘}; //便于输出
int n, //第一行符号总数
half, //全部符号总数一半
counter; //1计数,即“-”号计数
char **p; //符号存储空间
long sum; //符合条件的三角形计数
//t,第一行第t个符号
void Backtrace(int t)
{
int i, j;
if( t > n )
sum++;
else
for(i=0; i<2; ++i)
{
p[1][t] = i;//第一行第t个符号
counter += i; //“-”号统计
for(j=2; j<=t; ++j) //当第一行符号>=2时,可以运算出下面行的某些符号
{
p[j][t-j+1] = p[j-1][t-j+1]^p[j-1][t-j+2];//通过异或运算下行符号
counter += p[j][t-j+1];
}
if( (counter <= half) && ( t*(t+1)/2 - counter <= half) )//若符号统计未超过半数,并且另一种符号也未超过半数
Backtrace(t+1); //在第一行增加下一个符号
//回溯,判断另一种符号情况
for(j=2; j<=t; ++j)
counter -= p[j][t-j+1];
counter -= i;
}
}
int main()
{
freopen("input.txt","r",stdin);
while(scanf("%d", &n) != EOF)
{
counter = 0;
sum = 0;
half = n*(n+1)/2;
if( half%2 == 0 )
{//总数须为偶数,若为奇数则无解
half /= 2;
p = new char *[n+1];
for(int i=0; i<=n; ++i)
{
p[i] = new char[n+1];
memset(p[i], 0, sizeof(char)*(n+1));
}
Backtrace(1);
}
printf("%d\n", sum);}
return 0;
}
程序用一个t表示第一行中n个数中的第几个数,用第一重循环来赋值n个数的0或1值。然后再用一重循环,不断去更新每行未更新的。因为t不断加1,j每次都是从2开始,所以当t增大,当到j行时,明显j每次只是重复2-t之中,所以这样就实现了当第一行每增加一个数,都能补全为一个三角形了。
标签:highlight 字符 backtrace txt 通过 space back bsp tac
原文地址:http://www.cnblogs.com/521LOVE/p/7401082.html