标签: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