[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$块木板中从小到 ...
随机推荐
- 使用 Node.js 和 Express 构建基本的 Web API
使用 Node.js 和 Express 构建 Web API Web API Node.js 中的 http 模块 创建 Express 框架 Web 应用程序 Express 框架 Express ...
- php8.3开启jit技术
查看是否开启:$jitEnabled = ini_get('jit.enabled'); echo "JIT Enabled: " . ($jitEnabled == '1' ? ...
- windows edge浏览器免费复制网页文字
复制时,出现上面提示时候 使用edge浏览器打开链接,在http前面加入read: ,然后打开,即可复制 如果用js,可以参考https://www.cnblogs.com/rmticocean/p/ ...
- 【SQL】 Excel 批量编写SQL脚本
参考地址: https://zhuanlan.zhihu.com/p/134290191 有两种办法: 第一种,使用 & 拼接符号处理 ="INSERT INTO `my-info` ...
- windows11系统NVIDIA显卡驱动自动升级导致2070 Super显卡失效 —— 552.22版本自动升级到560.70版本后2070 Super型号显卡停止工作
操作系统 Windows11,旧版本显卡驱动是552.22,由于安装的是NVIDIA Geforce Experience后显卡驱动自动升级到560.77版本,然后显卡不再工作. 重新安装显卡驱动56 ...
- mysql 重置主键
开发时总是要向数据库写入测试数据,删掉以后id(自增主键)依然还是在增长,这个问题我遇到好多次,也都没有在意. 最近这个习惯被朋友嫌弃 = =||| 就在网上搜索了下mysql重置主键的办法: ALT ...
- java-多线程(下)
多线程简单入门(Java)(下篇:多线程Java中的使用) 目录 一.创建多线程 二.线程的安全 三.线程的通信 一.创建多线程 在Java中,多线程的创建有4种方式. 方式一:继承于Thread类; ...
- 9组-Alpha冲刺-5/6
一.基本情况 队名:不行就摆了吧 组长博客: https://www.cnblogs.com/Microsoft-hc/p/15546711.html 小组人数: 8 二.冲刺概况汇报 谢小龙 过去两 ...
- [nRF24L01+] 2. 芯片介绍
2. 芯片介绍 2.1. 特点 电源管理 掉电模式: 900nA 待机1模式: 26uA 2.2. 方框图
- 代码随想录Day17
654.最大二叉树 给定一个不重复的整数数组 nums . 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点,其值为 nums 中的最大值. 递归地在最大值 左边 的 子数组前缀 ...