[Tkey] A decorative fence
还是看看简单而富有美感的爆搜吧
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define tests int cases;cin>>cases;while(cases--)
int n,l;
vector<int> e;bool vis[21];int cnt=0;
void dfs(int p){
if(cnt==l) return;
if(p>n){
cnt++;
if(cnt==l){
for(int i:e) cout<<i<<" ";
cout<<endl;
}
return;
}
for(int i=1;i<=n;++i){
if(!vis[i]){
if(e.size()<=1){
e.push_back(i);vis[i]=1;
dfs(p+1);
e.pop_back();vis[i]=0;
}
else if((*(e.end()-1)>*(e.end()-2)&&*(e.end()-1)>i)||
(*(e.end()-1)<*(e.end()-2)&&*(e.end()-1)<i)){
e.push_back(i);vis[i]=1;
dfs(p+1);
e.pop_back();vis[i]=0;
}
}
}
}
signed main(){
tests{
e.clear();cnt=0;
cin>>n>>l;
dfs(1);
}
}
思路
这题爆搜肯定是不行,考虑一个事实:
假设 1xxxx 是 \(Rank=a\) 的一种方案,1yyyy 是 \(Rank=b\) 的另一种方案,而目标 \(Rank\ k\) 满足 \(a\le k\le b\),则有 \(Rank=k\) 的方案的首位一定是 \(1\).
跟我们猜数是一样的. 假设有个数给你猜,\(114\) 小了,\(191\) 大了,那你肯定知道这个数最高位是什么了.
所以我们就开个数组来转移并维护这个 \(Rank\) 值.
注意到 \(Rank\) 并不是非常好维护,我们可以考虑维护每种情况的方案数,然后按字典序从小到大依次加起来,这样就是 \(Rank\) 值了.
设 \(f[i][j][k]\) 为放入前 \(i\) 块木板构成的栅栏,当第 \(i\) 块木板的 \(Rank=j\) 时的方案数. 注意到这样还是不好维护,因为要考虑是高低高还是低高低,那么再开一维 \(k\) 来表示这个. \(k=1\) 时 \(1\) 为高,反之亦然.
那么这个转移非常好写,也不是本题的难点.
\]
这里唯一需要注意的是求和的范围. 因为我们这个 \(k\) 指代的是 \(Rank=k\),而且会涉及到选高的还是选低的的问题,也就有了 \(k\) 的范围的差异.
那么还很容易注意到,这个转移和 \(n,m\) 完全没有关系,所以从多测里提出来作为初始化.
然后就是按上面的思想来逼近我们要求的答案.
先来确定第一位吧,我们需要做的就是遍历每个 \(1\le i\le n\),只要有 \(\sum^{i}_{j=1}(f[n][j][0]+f[n][j][1])> m\),就能判定 \(j-1\) 是我们要求的那个第一位.
很显然,当我们之前几位选过某个数字,那我们就不能再选了,因此在之后的几次逼近中,我们还需要判断当前 \(Rank\) 的板子是不是已经被使用过了,然后进行类似的判断即可.
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define speed ios::sync_with_stdio(false);
#define tests int cases;cin>>cases;while(cases--)
#define clear(i) memset((i),0,sizeof (i))
int f[21][21][2]; //now fences have n planks, and the leftest planks ranking j
//k=0 means leftest is shorter,else taller
int n,m;
bool vis[21];
/*
f[i][j][1]=sum k{from 1 to j-1} f[i-1][k][0]
f[i][j][0]=sum k{from j to i-1} f[i-1][k][1]
*/
void prework(){
f[1][1][1]=1;f[1][1][0]=1;
for(int i=2;i<=20;++i){
for(int j=1;j<=i;++j){
for(int k=1;k<=j-1;++k){
f[i][j][1]+=f[i-1][k][0];
}
for(int k=j;k<=i-1;++k){
f[i][j][0]+=f[i-1][k][1];
}
}
}
}
signed main(){
prework();
speed tests{
cin>>n>>m;
clear(vis);
int now,last;
for(int i=1;i<=n;++i){
if(f[n][i][1]>=m){
last=i;now=1;break;
}
else{
m-=f[n][i][1];
}
if(f[n][i][0]>=m){
last=i;now=0;break;
}
else{
m-=f[n][i][0];
}
}
cout<<last<<" ";
vis[last]=true;
for(int i=2;i<=n;++i){
now=1-now;int rank=0;
for(int len=1;len<=n;++len){
if(vis[len]) continue;
rank++;
if((now==0 and len<last)or(now==1 and len>last)){
if(f[n-i+1][rank][now]>=m){
last=len;break;
}
else{
m-=f[n-i+1][rank][now];
}
}
}
vis[last]=true;
cout<<last<<" ";
}
cout<<endl;
}
}
[Tkey] A decorative fence的更多相关文章
- POJ1037 A decorative fence
题意 Language:Default A decorative fence Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 84 ...
- POJ1037 A decorative fence 【动态规划】
A decorative fence Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 6489 Accepted: 236 ...
- A decorative fence
A decorative fence 在\(1\sim n\)的全排列\(\{a_i\}\)中,只有大小交错的(即任意一个位置i满足\(a_{i-1}<a_i>a_{i+1}ora_{i- ...
- poj 1037 A decorative fence
题目链接:http://poj.org/problem?id=1037 Description Richard just finished building his new house. Now th ...
- OpenJ_Bailian - 1037 A decorative fence
Discription Richard just finished building his new house. Now the only thing the house misses is a c ...
- POJ1037A decorative fence(动态规划+排序计数+好题)
http://poj.org/problem?id=1037 题意:输入木棒的个数n,其中每个木棒长度等于对应的编号,把木棒按照波浪形排序,然后输出第c个; 分析:总数为i跟木棒中第k短的木棒 就等于 ...
- POJ1037A decorative fence(好dp)
1037 带点组合的东西吧 黑书P257 其实我没看懂它写的嘛玩意儿 这题还是挺不错的 一个模糊的思路可能会好想一些 就是大体的递推方程 dp1[][]表示降序 dp2[][]表示升序 数组的含义为长 ...
- 【POJ1037】A decorative fence(DP)
BUPT2017 wintertraining(15) #6C 题意 给长度n的数列,1,2,..,n,按依次递增递减排序,求字典序第k小的排列. 题解 dp. up[i][j]表示长度为j,以第i小 ...
- poj1037 [CEOI 2002]A decorative fence 题解
---恢复内容开始--- 题意: t组数据,每组数据给出n个木棒,长度由1到n,除了两端的木棒外,每一根木棒,要么比它左右的两根都长,要么比它左右的两根都短.即要求构成的排列为波浪型.对符合要求的排列 ...
- $Poj1037\ A\ Decorative\ Fence$ 计数类$DP$
Poj AcWing Description Sol 这题很数位$DP$啊, 预处理$+$试填法 $F[i][j][k]$表示用$i$块长度不同的木板,当前木板(第$i$块)在这$i$块木板中从小到 ...
随机推荐
- GIS前沿技术
无论是初步接触到GIS的学生,还是对GIS已经有一定的了解的从业者,肯定都非常关心两个问题:GIS有没有发展前景,GIS有哪些应用价值? 关于这两个问题,笔者的答案是GIS作为一门融合了空间数据采集. ...
- 封装的grid控件
class CGridCtrl : public CWnd { DECLARE_DYNAMIC(CGridCtrl) public: void Create(CWnd* pParent, DWORD ...
- BeanUtils.copyProperties无法复制list对象,替换为lambda表达式
List<Setmeal> setmeals = setmealMapper.selectList(queryWrapper); List<SetmealVO>vo=new A ...
- Scratch植物大战僵尸全套素材包免费下载
scratch植物大战僵尸全套素材包,包含227个丰富多样的素材,涵盖角色.背景.动态gif.为Scratch创作者提供丰富资源,助力创作精彩作品. 免费下载地址:www.xiaohujing.com ...
- docker 概念,安装,启动,运行
docker概念,安装,启动,运行模式 docker的概念 镜像(image) 模板,可以通过模板来创建容器服务,tomcat镜像===>run==>tomacat01容器(提供服务),通 ...
- 【Game】安装EA的Origin(烂橘子)平台太慢 解决办法
情况是购买了Steam上的爹5,本体下载完成之后需要安装烂橘子平台 然后发现走官方提供下载的平台根本装不上来,安装贼慢 折腾什么配置文件,改HOST都是一些乱七八糟的操作,都没说清楚这干嘛用的 解决方 ...
- 【Docker】01 概述
什么是Docker? 一个开源的应用容器引擎 由Go语言开发而成,遵循Apache2.0开源协议 允许开发者打包自己的应用或者依赖包组件到一个轻量级可移植的容器中 Docker容器采用沙箱机制,相互之 ...
- 【Vue】Re18 Router 第五部分(KeepAlive)
一.KeepAlive概述 默认状态下,用户点击新的路由时,是访问新的组件 那么当前组件是会被销毁的,然后创建新的组件对象出来 如果某些组件频繁的使用,将造成内存空间浪费,也吃内存性能 所以需求是希望 ...
- python高性能计算:cython使用openmp并行 —— 报错:undefined symbol: omp_get_thread_num
test.pyx文件: from cython.parallel cimport parallel from openmp cimport omp_get_thread_num cpdef void ...
- 强化学习入门书籍《DeepReinforcementLearningHands-On-SecondEdition》
前段时间在网上买了本强化学习入门的书籍,即<Deep-Reinforcement-Learning-Hands-On>,虽然是影印版的,但是感觉还是可以看看的,说的也蛮易懂的,感觉比现在市 ...