hdu2510 dfs打表
2016-05-01 16:35
246 查看
符号三角形
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1375 Accepted Submission(s): 731
[align=left]Problem Description[/align]
符号三角形的 第1行有n个由“+”和”-“组成的符号 ,以后每行符号比上行少1个,2个同号下面是”+“,2个异 号下面是”-“ 。计算有多少个不同的符号三角形,使其所含”+“ 和”-“ 的个数相同 。 n=7时的1个符号三角形如下:
+ + - + - + +
+ - - - - +
- + + + -
- + + -
- + -
- -
+
[align=left]Input[/align]
每行1个正整数n <=24,n=0退出.
[align=left]Output[/align]
n和符号三角形的个数.
[align=left]Sample Input[/align]
15 16 19 20 0
[align=left]Sample Output[/align]
15 1896
16 5160
19 32757
20 59984
这个题并不难, 只要在第一行上dfs就行了, 他下面的那些行可以由第一行得到.
有个剪枝技巧是:
求n时, 有(1+n)/n*2 个符号(等差数列求和), 如果符号数不是偶数的话, 不用算了, 直接就是0.
无奈我写的dfs效率不行, 重复工作太多,时间超了, 但是好像一共就几个数啊, 所以宝宝不要脸地打表AC了.
打表AC代码:
#include <iostream> using namespace std; int result[24]={0,0,4,6,0,0,12,40,0,0,171,410,0,0,1896,5160,0,0,32757,59984,0,0,431095,822229}; int main() { int n; cin>>n; while(n!=0) { cout<<n<<" "<<result[n-1]<<endl; cin>>n; } return 0; }
宝宝写的dfs算法:
#include<cstdio> #include<cstring> #include<iostream> using namespace std; int red[30], n,tot; int mp[30][30]; int ans[30]; bool check(){ int pluss,minu; pluss=minu=0; int sum=(1+n)*n/2; for(int i=0;i<n;i++){ mp[0][i]=red[i]; if(mp[0][i]=='+')pluss++; else minu++; if(pluss>(sum/2))return false; if(minu>(sum/2))return false; } for(int i=1;i<n;i++){ for(int j=0;j<n-i;j++){ mp[i][j]=(mp[i-1][j]==mp[i-1][j+1]?'+':'-'); if(mp[i][j]=='+')pluss++; else minu++; if(pluss>(sum/2))return false; if(minu>(sum/2))return false;//剪枝 } } return minu==pluss; } void dfs(int deep){ if(deep>=n){ if(check())tot++; return; } red[deep]='+'; dfs(deep+1); red[deep]='-'; dfs(deep+1); } int main(){ ans[1]=0; for(n=2;n<=24;n++){ if(((1+n)*n/2)%2==1){//剪枝 ans =0; continue; } tot=0; dfs(0); ans =tot; printf("%d %d\n",n,ans ); } while(cin>>n && n){ printf("%d %d\n",n,ans ); } return 0; }
大神写的
#include<stdio.h> #include<string.h> int ans[30]; int a[30][30];//用于保存每个n的第一层的状态的中间过程 int count;//记录1的个数 void DFS(int n) { int i,j; if(n>24) return ; for(i=0;i<=1;i++) { a[1] =i;//只需要暴力第一行即可 count+=i; for(j=2;j<=n;j++) { a[j][n-j+1]=a[j-1][n-j+1]^a[j-1][n-j+2]; count+=a[j][n-j+1]; } if(count*2==n*(n+1)/2) ans ++; DFS(n+1); count-=i; for(j=2;j<=n;j++) { a[j][n-j+1]=a[j-1][n-j+1]^a[j-1][n-j+2]; count-=a[j][n-j+1]; } } } int main() { int i,j,k,n; memset(ans,0,sizeof(ans)); count=0; DFS(1); while(scanf("%d",&n)!=EOF) { if(!n) break; printf("%d\n",ans ); } return 0; }
相关文章推荐
- 异常 2 problemscvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be foun
- 常用wifi功能集合工具类
- Android开源项目及库
- Provisioning Services 7.8 入门系列教程之一 部署学习环境介绍
- HDU-4599 Dice (概率DP)
- HDOJ5671
- 图论判环模板
- innerHTML、getElementsByName()、getElementsByTagName()
- Linux内核学习总结
- 说一说windows原生docker及windows Server Container , Hyper Container 之间的关系(学习总结)
- 链表结点的插入
- LightOJ 1341
- Chaikin细分曲线
- 用C语言写的注释转换
- 重载内核全程分析笔记
- 第二章 关系模型介绍
- 新手在windows7下安装ubuntu15.10
- 全国SHP地图数据赠送
- 移动开发入门指南
- 希尔排序(Shell)