[jzoj]1261. 数字游戏(搜索+剪枝)
来源:互联网 发布:淘宝被恶意差评怎么办 编辑:程序博客网 时间:2024/06/06 03:41
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 16
3 9
0 0
Sample Output
3 1 2 4
1 3 2
Data Constraint
Hint
【样例说明】
开始排列: 3 1 2 4
第一次操作:3+1=4 1+2=3 2+4=6
得到: 4 3 6
第二次得到: 7 9
最后就是: 16
【注释】
数据保证有解。
对于30%的数据,保证该组里的每个N都不超过10。
对于100%的数据,保证有每个N不超过20,且每组数据的个数不超过10。
Solution
暴力很显然会超时.
优化一、系数
我们知道原本序列的A,到最终序列T,每一个数其实都乘上了一个对应的系数,这个系数可以预处理.
优化二、对称性
题目要求字典序最小,我们知道系数是有对称性的,所以当两个对称的x,y,有a[y]
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>using namespace std;int n,t,i,j,k,maxmax,minmin,l1,l2,kk,len;int a[21][21][21];int s[21],d[21],x[21],have[21];bool bz[21],flag;void dfs(int k,int sum){ if (k>n) { if (sum==t) { for (j=1;j<=n-1;j++) printf("%d ",x[j]); printf("%d\n",x[n]); flag=false; } return; } if (sum+s[k]>t) return; //优化一-合法性. if (sum+n*s[k]<t) return; //优化一-合法性. kk=k; maxmax=minmin=len=0; l1=(n+1)/2; l2=l1+1; for (j=n;j>=1;j--) if (bz[j]) have[++len]=j; for (j=1;j<=len;j++) { if (l1<k) l1=0; while (l2<k) l2++; if (d[l1]>=d[l2]) maxmax+=d[l1]*have[j],minmin+=d[l1--]*have[len-j+1]; else maxmax+=d[l2]*have[j],minmin+=d[l2++]*have[len-j+1]; } if (sum+maxmax<t) return; if (sum+minmin>t) return; int up; if (k<=(n+1)>>1) up=1; else up=x[n-k+1]+1; //优化二-对称性 for (int i=up;i<=n;i++) if ((bz[i])&&(flag)) { x[k]=i; bz[i]=false; dfs(k+1,sum+i*d[k]); bz[i]=true; }}int main(){ freopen("easy.in","r",stdin); freopen("easy.out","w",stdout); scanf("%d%d",&n,&t); memset(bz,1,sizeof(bz)); while (n+t>0){ memset(a,0,sizeof(a)); memset(d,0,sizeof(d)); for (i=1;i<=n;i++) a[1][i][i]=1; for (i=2;i<=n;i++) for (j=i;j<=n;j++) for (k=1;k<=n;k++) a[i][j][k]=a[i-1][j-1][k]+a[i-1][j][k]; for (k=1;k<=n;k++) d[k]=a[n][n][k]; //优化三-系数 s[n+1]=1e8; s[n]=d[n]; for (k=n-1;k>=1;k--) s[k]=s[k+1]+d[k]; flag=true; dfs(1,0); scanf("%d%d",&n,&t); }}
- [jzoj]1261. 数字游戏(搜索+剪枝)
- BSOJ 2963:数字游戏 搜索+剪枝
- jzoj 2032. 数字游戏
- jzoj 1261 数字游戏
- 【BashuOJ2963】数字游戏-DFS+剪枝
- jzoj P2131【2017.4.21普及】数字游戏
- poj_1011_sticks(搜索+剪枝)
- hdu4499(剪枝搜索)
- 搜索(1):剪枝
- poj1190(搜索剪枝)
- poj1011Sticks(搜索+剪枝)
- poj1190 生日蛋糕 (搜索剪枝)
- poj1011 stick(搜索,剪枝)
- FZU--2188(搜索+剪枝)
- hdu 5305 (搜索+剪枝)
- 搜索(2):估值型剪枝
- POJ 2531(搜索剪枝)
- poj 1011 搜索(剪枝)
- mvn依赖解决冲突
- Java日志终极指南
- 网络爬虫Python试验
- 提高Java开发效率,Idea必装的几款插件
- Stockbroker Grapevine
- [jzoj]1261. 数字游戏(搜索+剪枝)
- Firefox安装selenium自动化测试教程
- hdu1176——免费馅饼
- 平方根的C语言实现(一) —— 浮点数的存储
- zoj2818 Root of the Problem 简单数学 开方
- redis关闭服务失败报错:(error) ERR Errors trying to SHUTDOWN. Check logs.
- 1010. Radix (25)
- C#学习笔记壹---字符串处理技术(1)
- HDU 6015 Gameia【博弈】