还是看看简单而富有美感的爆搜吧
#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\) 为高,反之亦然.

那么这个转移非常好写,也不是本题的难点.

\[\begin{cases}f[i][j][1]=\sum_{1\le k\le j-1} f[i-1][k][0]\\f[i][j][0]=\sum_{j\le k\le i-1} f[i-1][k][1]\end{cases}
\]

这里唯一需要注意的是求和的范围. 因为我们这个 \(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的更多相关文章

  1. POJ1037 A decorative fence

    题意 Language:Default A decorative fence Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 84 ...

  2. POJ1037 A decorative fence 【动态规划】

    A decorative fence Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 6489   Accepted: 236 ...

  3. A decorative fence

    A decorative fence 在\(1\sim n\)的全排列\(\{a_i\}\)中,只有大小交错的(即任意一个位置i满足\(a_{i-1}<a_i>a_{i+1}ora_{i- ...

  4. poj 1037 A decorative fence

    题目链接:http://poj.org/problem?id=1037 Description Richard just finished building his new house. Now th ...

  5. OpenJ_Bailian - 1037 A decorative fence

    Discription Richard just finished building his new house. Now the only thing the house misses is a c ...

  6. POJ1037A decorative fence(动态规划+排序计数+好题)

    http://poj.org/problem?id=1037 题意:输入木棒的个数n,其中每个木棒长度等于对应的编号,把木棒按照波浪形排序,然后输出第c个; 分析:总数为i跟木棒中第k短的木棒 就等于 ...

  7. POJ1037A decorative fence(好dp)

    1037 带点组合的东西吧 黑书P257 其实我没看懂它写的嘛玩意儿 这题还是挺不错的 一个模糊的思路可能会好想一些 就是大体的递推方程 dp1[][]表示降序 dp2[][]表示升序 数组的含义为长 ...

  8. 【POJ1037】A decorative fence(DP)

    BUPT2017 wintertraining(15) #6C 题意 给长度n的数列,1,2,..,n,按依次递增递减排序,求字典序第k小的排列. 题解 dp. up[i][j]表示长度为j,以第i小 ...

  9. poj1037 [CEOI 2002]A decorative fence 题解

    ---恢复内容开始--- 题意: t组数据,每组数据给出n个木棒,长度由1到n,除了两端的木棒外,每一根木棒,要么比它左右的两根都长,要么比它左右的两根都短.即要求构成的排列为波浪型.对符合要求的排列 ...

  10. $Poj1037\ A\ Decorative\ Fence$ 计数类$DP$

    Poj  AcWing Description Sol 这题很数位$DP$啊, 预处理$+$试填法 $F[i][j][k]$表示用$i$块长度不同的木板,当前木板(第$i$块)在这$i$块木板中从小到 ...

随机推荐

  1. Node.js 处理 File

    Node.js 处理 File fs 模块 常规使用 运用递归遍历目录树 创建文件和目录 读写文件 path 模块 对于 file 的理解,此处 fs 模块 Node.js 提供了处理文件系统的内置模 ...

  2. XCode 编译 PAG 源码

    最近工作中要使用PAG替换Lottie,为了方便阅读源码,使用XCode对其源码进行了编译. 1 下载源码 编译源码首先要下载源码,有关PAG源码可直接到github上下载. 2 添加相关依赖 下载源 ...

  3. RHCA rh442 002 监控工具 脏页 块设备名 缓存

    sar 看某一个时间的数据 sar -d 1 5 与iostat类似 计算机识别设备按编号识别 0-15预留出 8 为iscsi设备 做一个块设备名 名字不重要是给人看的,重要的是编号 8 17(主编 ...

  4. 【Java】Vue-Element-Admin 嵌入Druid监控面板

    我看到若依做了Druid面板的嵌入,我自己的项目干脆也做一个 一.后台服务SpringBoot: Druid配置项: spring: datasource: url: jdbc:mysql://127 ...

  5. How to evaluate the Messi Hong Kong fraud incident?

    Who is Lionel Messi? URL: https://en.wikipedia.org/wiki/Lionel_Messi As a famous football player, Me ...

  6. 一个好主板对CPU超频的现实意义————一次超频经历 (z390ws华硕工作站主板+i7-9700k CPU ,Ubuntu18.04.5系统,8核心超频 5.2Ghz以上,单核心满负荷运转可以稳定运行10多分钟后才重启)

    本人于今年2020年1月份在某宝上购买了一款workstation主板,也就是工作站主板,传说中的华硕Z390WS主板(购入价格为3900元),由于当时手里有些小钱,又弄了一个大蝴蝶1350w的电源( ...

  7. 乌克兰学者的学术图谱case3

    ============================================ 背景: 弗兰采维奇材料问题研究是欧洲最大的材料科研院所,在核电.航空.航天.军工及其他装备制造领域的先进材料研 ...

  8. Gitee官网大规模封禁开源项目,如想解禁则需手动提交审核,在此过程中一些项目的信息也被gitee官方修改!!!

    由于美国政府对中国的各种打压和制裁,为了支持国产软件我已经将GitHub上的大多数代码库迁移到了gitee上,虽然我的开源库基本都是个人学习时候的一些代码并不是什么成品项目代码,但是不管力量大小也都支 ...

  9. vue项目之登录功能

    1.背景 在上一节的学习中我们基本上完成了登录的表单输入框界面如下: 代码: <!-- 输入框--> <el-form label-width="0px" cla ...

  10. quartz执行卡死--强制中断线程

    在quartz中经常会碰到由于网络问题或者一些其他不稳定因素导致的线程卡死问题,这往往会导致数据处理的延时.而有时候一时无法定位到卡死的原因,为了降低系统风险,我们就会希望有一个超时机制,当执行超时时 ...