jzoj 1261 数字游戏
来源:互联网 发布:win10优化驱动器要几遍 编辑:程序博客网 时间:2024/06/05 16:01
Description
Charles和sunny在玩一个简单的游戏。若给出1~n的一个排列A,则将A1、A2相加,A2、A3相加……An-1、An相加,则得到一组n-1个元素的数列B;再将B1、B2相加,B2、B3相加,Bn-2、Bn-1相加,则得到一组n-2个元素的数列……如此往复,最终会得出一个数T。而Charles和sunny玩的游戏便是,Charles给出n和T,sunny在尽可能短的时间内,找到能通过上述操作得到T且字典序最小的1~n的排列。(sunny大声说:“What an easy game!”,接着几下就给出了解),Charles觉得没意思,就想和你玩,当然,你可以用一种叫做“电子计算机”的东西帮你。
Input
本题有多组数据,对于每组数据:一行两个整数n(0< n<=20),t即最后求出来的数。两个0表示输入结束。
Output
对于每组测试数据输出一行n个整数,用空格分开,行尾无多余空格,表示求出来的满足要求的1~n的一个排列。
Sample Input
4 163 90 0
Sample Output
3 1 2 41 3 2
Data Constraint
对于30%的数据,保证该组里的每个N都不超过10。对于100%的数据,保证有每个N不超过20,且每组数据的个数不超过10。
Solution
可以通过观察发现,t是由这个n的排列的每个数乘上一个系数得到,系数是杨辉三角第n行。若直接dfs,就会超时,所以需要剪枝。1.若已经找到答案,结束dfs2.若当前的和加上后面能算出的最大值仍小于t,返回上层。3.若当前的和加上后面能算出的最小值仍大于t,返回上层。4.由于系数对称,而要找字典序最小的序列,所以,当系数相同时,小的数一定在前面。
#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>using namespace std;#define N 25int f[N][N];int q[N],t[N],x[N];int n,m;bool b;void pre(){ memset(f,0,sizeof(f)); f[1][1]=1; for (int i=2;i<N;++i) for (int j=1;j<=i;++j) f[i][j]=f[i-1][j-1]+f[i-1][j];}bool comp(int x,int y){ return x>y;}bool pd(int dep,int s){ int an=s; for (int i=dep;i<=n;++i) x[i-dep]=f[n][i]; sort(x,x+n-dep+1,comp); /*for (int i=0;i<=n-dep;++i) printf("%d ",x[i]); printf("\n");*/ int j=0; for (int i=n;i>=1;--i) if (t[i]==0) { an+=i*x[j]; j++; } //printf("max=%d\n",an); if (an<m) return true; an=s; j=0; for (int i=1;i<=n;++i) if (t[i]==0) { an+=i*x[j]; j++; } //printf("min=%d\n",an); if (an>m) return true; return false;}void dfs(int dep,int s){ /*printf("%d,%d\n",dep,s); for (int i=1;i<=n;++i) printf("%d ",t[i]); printf("\n");*/ if (b==1) return; if (dep==n) { if (s==m) { for (int i=1;i<=n;++i) printf("%d ",q[i]); printf("\n"); b=1; } return; } if (s>m) return; if (pd(dep+1,s)) return; if (dep>n/2 && q[dep]<q[n-dep+1]) return; for (int i=1;i<=n;++i) if (t[i]==0) { t[i]=1; q[dep+1]=i; dfs(dep+1,s+i*f[n][dep+1]); t[i]=0; }}int main(){ freopen("easy.in","r",stdin); freopen("easy.out","w",stdout); pre(); scanf("%d%d",&n,&m); while (not(n==0 && m==0)) { b=0; memset(t,0,sizeof(t)); dfs(0,0); scanf("%d%d",&n,&m); } return 0;}
阅读全文
1 0
- jzoj 1261 数字游戏
- jzoj 2032. 数字游戏
- jzoj P2131【2017.4.21普及】数字游戏
- [jzoj]1261. 数字游戏(搜索+剪枝)
- jzoj 2570. 【NOIP2011模拟9.17】数字生成游戏
- JZOJ 4.22 2131——【2017.4.21普及】数字游戏
- JZOJ.1764. 游戏
- 【JZOJ 3082】骰子游戏
- 【JZOJ 3082】 骰子游戏
- jzoj 2050. 【8.18】游戏
- JZOJ 1322 硬币游戏
- JZOJ 1322. 硬币游戏
- jzoj 1591. 【普及模拟】游戏
- jzoj 1145. 简单游戏(easygame)
- 【JZOJ 3871】无聊的游戏
- 【JZOJ 3871】 无聊的游戏
- jzoj P1593 电视游戏问题
- 数字游戏
- LocalDateTime计算时间差
- 试一试 kolla部署OpenStack Ocata
- 排序算法稳定性
- 朴素神经网络原理抛砖引玉
- 反射
- jzoj 1261 数字游戏
- [jzoj]1205. 帮助Bub(“后效性”DP)
- 理解javas原型
- 深度学习最全优化方法总结比较(SGD,Adagrad,Adadelta,Adam,Adamax,Nadam)
- redis特性之多数据库及jedis操作
- java基础编程:输出九九乘法表
- Linux内核调试技术——kprobe使用与实现
- python与编码
- 2017百度之星初赛(B)1001Chess------hdu6114