NYOJ491-幸运三角形
2014-04-21 16:32
453 查看
幸运三角形
[align=center]时间限制:1000 ms | 内存限制:65535 KB[/align][align=center]难度:3[/align]
描述
话说有这么一个图形,只有两种符号组成(‘+’或者‘-’),图形的最上层有n个符号,往下个数依次减一,形成倒置的金字塔形状,除第一层外(第一层为所有可能情况),每层形状都由上层决定,相邻的符号相同,则下层的符号为‘+’,反之,为‘-’;如下图所示(n = 3 时的两种情况):
如果图中的两种符号个数相同,那这个三角形就是幸运三角形,如上图中的图(2).
输入有多组测试数据(少于20组)。
每行含一个整数n(0<n<20)。输出输出相应的幸运三角形个数。样例输入
3 4
样例输出
4 6
由于数据数值较小,所以深搜超时之后果断打表输出。
代码一:深搜(超时)
#include<iostream> using namespace std; int s; int fun(int n) { int sum=0; for(int i=1;i<=n;i++) sum+=i; if(sum%2) return 0; return 1; } void check(char* str,int n) { int cnt=0,sum=0; //sum为1+2+3+..+n的和,cnt为该字符串所构成的三角形中'+'的个数 while(n>1) { sum+=n; for(int i = 0;i < n ;i ++) { if(str[i]=='+') cnt++; } for(int i = 0;i < n-1;i ++) { if(str[i]==str[i+1]) str[i]='+'; else str[i]='-'; } n--; } if(str[0]=='+') cnt++; if(cnt*2==sum+1) //是幸运三角形,s++ s++; } void dfs(char* str,int cur,int n) { if(cur==n) { check(str,n); //每深搜出一串长度为n的字符串就检查其是否可以构成幸运三角形 return; } str[cur]='+'; dfs(str,cur+1,n); str[cur]='-'; dfs(str,cur+1,n); } int main() { char str[25]; int n,cur=0; while(cin>>n) { if(!fun(n)) cout<<0<<endl; else { s=0; dfs(str,cur,n); cout<<s<<endl; } } return 0; }
代码二:打表
#include<iostream> using namespace std; int main() { int num[25]={0,0,0,4,6,0,0,12,40,0,0,171,410,0,0,1896,5160,0,0,32757,59984}; int n; while(cin>>n) cout<<num <<endl; return 0; }
代码三:深搜AC
Copy的最有代码,边计算边回溯,避免了重复计算。没怎么看懂,以后再看吧。。。
#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) //只取 0('+') 或者 1('-') { 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() { 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; }
相关文章推荐
- js获取上传文件扩展名
- IOS编程教程(五)自定义UITableView的表单元格
- Sort List
- HDU 4433 locker (线性dp)
- 使用信号量和关键区来实现生产者消费者
- Git教程
- Linux初学者之网络配置(命令)
- JDK中rt.jar、tools.jar和dt.jar作用
- 【define宏定义和const常量定义之间的区别】
- Go lang concurrency: select with channels
- Extjs4.0 Ext.Class
- 妙趣横生的算法--二叉树
- 闲扯 Javascript 02 全选、不选、反选
- C#-Activex插件操作指南
- HTTP错误代码详细介绍
- 网关设置
- oracle pl/sql之函数(function)
- Openwrt移植IMX6之增加u-boot支持
- socket.error C2011: “sockaddr”: “struct”类型重定义
- STA线程模型中操纵串口的注意点