首先明确一下cute fence的含义, 它是指一组"单调区间仅为1"的 1~n 的排列数, 如果我们知道了n个木板时有多少种这样的排列,就可以
通过递归,反向输出序列.
定义dp[n]为n个木板时的"cute fence"数,我们首先的目标是要得到dp[1~n]的值.
设想此时为了构造一段cute fence,需要知道:
1.第一块木板的长度L1;
2.下一块木板的长度L2
(1) 若 L1>L2,则构造的是以L1为起始木板的下降fence;
(2) 若 L1<L2,则构造的是以L1为起始木板的上升fence;
显然如果是2的第1种情况,接下来应该构造以L2为起始木板的上升fence;同样第2种情况应该构造以L2为起始木板的下降fence.
于是问题被递归,并得到dp方程.
dp[i][j].up为以长度为i的木板开头,构造长度为j的上升fence的数量.
dp[i][j].up=sum(dp[t][j-1].down) (i+1<=t<=max)
下降fence数类似.
接下来就是个经典的根据dp方程反向打印问题.


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
typedef long long LL;
typedef struct node
{
LL up;
LL down;
}node;
LL n,c;
node dp[25][25];
int ans[25];
int use[25];
void init_dp()
{
int i,j,k;
dp[2][1].up=1;
dp[2][2].down=1;
for(i=3;i<=20;i++)
for(j=1;j<=i;j++)
{
for(k=1;k<=j-1;k++)
dp[i][j].down+=dp[i-1][k].up;
for(k=j;k<=i-1;k++)
dp[i][j].up+=dp[i-1][k].down;
}
}
void print_ans(int cur)
{
if(cur>n)return;
print_ans(cur+1);
if(cur==1)printf("%d\n",ans[cur]);
else printf("%d ",ans[cur]);
}
int find(int ind)
{
int i,count=0;
for(i=1;i<=n;i++)
{
if(!use[i])count++;
if(count==ind)return i;
}
return 0;
}
void dfs(LL order, int restl, int cur, string stat)
{
int i;
if(restl==1)
{
for(i=1;i<=n;i++)
if(!use[i])break;
ans[restl]=i;
print_ans(1);
return ;
}
if(stat=="up")
{
for(i=cur;i<=restl;i++)
if(order-dp[restl][i].down>0)order-=dp[restl][i].down;
else break;
ans[restl]=find(i);
use[ans[restl]]=1;
dfs(order,restl-1,i,"down");
}
else
{
for(i=1;i<cur;i++)
if(order-dp[restl][i].up>0)order-=dp[restl][i].up;
else break;
ans[restl]=find(i);
use[ans[restl]]=1;
dfs(order,restl-1,i,"up");
}
}
int main()
{
int cases,i;
freopen("test.txt","r",stdin);
scanf("%d",&cases);
init_dp();
while(cases--)
{
scanf("%I64d%I64d",&n,&c);
if(n==1){printf("1\n");continue;}
for(i=1;i<=n;i++)
if(c-dp[n][i].down-dp[n][i].up>0)
c-=dp[n][i].down+dp[n][i].up;
else break;
ans[n]=i;use[ans[n]]=1;
if(c-dp[n][i].down>0)
{
c-=dp[n][i].down;
dfs(c,n-1,i,"up");
}
else dfs(c,n-1,i,"down");
memset(use,0,sizeof(use));
memset(ans,0,sizeof(ans));
}
return 0;
}