poj1037(dP+排列计数)
来源:互联网 发布:数据录入员工作的细节 编辑:程序博客网 时间:2024/06/16 14:46
http://poj.org/problem?id=1037
例八: POJ 1037 一个美妙的栅栏
N 个木棒, 长度分别为1, 2, …, N.
构成美妙的栅栏
除了两端的木棒外,每一跟木棒,要么比它左右的两根都长,要
么比它左右的两根都短。
即木棒呈现波浪状分布,这一根比上一根长了,那下一根就比这
一根短,或反过来
问题: 符合上述条件的栅栏建法有很多种,对
于满足条件的所有栅栏, 按照字典序(从左到
右, 从低到高) 排序。
给定一个栅栏的排序号,请输出该栅栏, 即每
一个木棒的长度.
例题: POJ 1037 一个美妙的栅栏
输入数据
第一行是测试数据的组数 K (1 <= K <= 100)。接下来的K行,
每一行描述一组输入数据.
每一组输入数据包括两个整数 N 和 C. N ( 1 <= N <= 20) 表示
栅栏的木棒数, C表示要找的栅栏的排列号.
输出数据
输出第C个栅栏, 即每一个木棒的长度
设20个木棒可组成的栅栏数是T; 我们假设 T
可以用64-bit长整数表示,1 < C <= T
例题: POJ 1037 一个美妙的栅栏
输入样例
输出样例
2
2 1
3 3
1 2
2 3 1
80
解题思路
问题抽象:给定1到N 这N个数字,将这些数字高低交替进
行排列 ,把所有符合情况的进行一个字典序排列,问第C个
排列是一个怎样的排列
总体思想
动归 + 排列计数
动归
动归解题思路
1) 设 A[i] 为i根木棒所组成的合法方案数目。看看能否找出A[i]和A[i-1]
或A[i-j]之间的递推关系(所有木棒总数是i)。称i根木棒的合法方案集合
为S(i)
2) 在选定了某根木棒x作为第一根木棒的情况下,剩下i-1根木棒的合法
方案数是A[i-1]。但是,这A[i-1]种方案,并不是每种都能和x形成新的
合法方案。将第一根比第二根长的方案称为DOWN方案,第一根比第
二根短的称为UP方案,则,S(i-1)中,第一根木棒比x长的DOWN方
案,以及第一根木棒比x短的UP方案,才能和x构成S(i)中的方案。
动归解题思路
3) 置A[i] = 0。先枚举x。然后针对每个x,枚举x后面的那根木棒y。如果 y >
x(x<y的情况类推),则:
A[i] += 以y打头的DOWN方案数
但以y打头的DOWN方案数,又和y的长短有关。
于是难以直接从 A[i-1]或 A[i-j]推出 A[i]
4) 考虑将A[i]这种粗略的状态描述方式细化,即加上限制条件后分类。设
A[i] = ∑ B[i][k] k = 1….i
B[i][k] 是S(i)中以第k短的木棒打头的方案数。尝试对 B 进行动归。第k短
,指的是i根木棒中第k短。
动归解题思路
5) B[i][k] = ∑ B[i-1][M](DOWN)+ ∑ B[i-1][N](UP)
M = k ... i-1 , N = 1… k-1
还是没法直接推。于是把B再分类细化:
B[i][k] = C[i][k][DOWN] + C[i][k][UP]
C[i][k][DOWN] 是S(i)中以第k短的木棒打头的DOWN方案数。然后试图对C进行动
归
C[i][k][UP] = ∑ C[i-1][M][DOWN]
M = k ... i -1
C[i][k][DOWN] = ∑ C[i-1][N][UP]
N = 1… k-1
初始条件:C[1][1][UP]=C[1][1][DOWN] = 1
动归解题思路
经验:当选取的状态,难以进行递推时(分解出的子问题和原
问题形式不一样,或不具有无后效性),考虑将状态增加限制
条件后分类细化,即增加维度,然后在新的状态上尝试递推
排序计数
如1,2,3,4的全排列,共有4!种,求第10个的排列是(从1计
起)?
先试首位是1,后234有3!=6种<10,说明首位1偏小,问题转换成
求2开头的第(10-6=4)个排列,而3!=6 >= 4,说明首位恰是2。
第二位先试1(1没用过),后面2!=2个<4,1偏小,换成3(2用过
了)为第二位,待求序号也再减去2!,剩下2了。而此时2!>=2,
说明第二位恰好是3。
第三位先试1,但后面1!<2,因此改用4。末位则是1了。
这样得出,第10个排列是2-3-4-1。
排序计数
本题待求方案的序号为C
本题就是先假设第1短的木棒作为第一根,看此时的方案数
P(1)是否>=C,如果否,则应该用第二短的作为第一根,C 减去P(1)
,再看此时方案数P(2)和C比如何。如果还 < C ,则应以第三短的
作为第一根,C再减去P(2) ….
若发现 第 i短的作为第一根时,方案数已经不小于C,则确定
应该以第i短的作为第一根, C减去第 i短的作为第一根的所有方案
数,然后再去确定第二根….
微调:以第i短的木棒作第k根时,有UP和DOWN两类方案,
先用DOWN的方案数和C比较
//POJ1037 A decorative fence by Guo Wei#include <iostream>#include <algorithm>#include <cstring>#include<cstdio>using namespace std;const int UP =0;const int DOWN =1;const int MAXN = 25;long long C[MAXN][MAXN][2]; //C[i][k][DOWN] 是S(i)中以第k短的木棒打头的DOWN方案数,C[i][k][UP] 是S(i)中以第k短的木棒打头的UP方案数,第k短指i根中第k短void Init(int n){ memset(C,0,sizeof(C)); C[1][1][UP] = C[1][1][DOWN] = 1; for( int i = 2 ; i <= n; ++ i ) for( int k = 1; k <= i; ++ k ) //枚举第一根木棒的长度 { for( int M = k; M <i ; ++M ) //枚举第二根木棒的长度 C[i][k][UP] += C[i-1][M][DOWN]; for( int N = 1; N <= k-1; ++N ) //枚举第二根木棒的长度 C[i][k][DOWN] += C[i-1][N][UP]; }//总方案数是 Sum{ C[n][k][DOWN] + C[n][k][UP] } k = 1.. n;}void Print(int n, long long cc){ long long skipped = 0; //已经跳过的方案数 int seq[MAXN]; //最终要输出的答案 int used[MAXN]; //木棒是否用过 memset(used,0,sizeof(used)); for( int i = 1; i<= n; ++ i ) //依次确定每一个位置i的木棒序号 { long long oldVal = skipped; int k; int No = 0; //k是剩下的木棒里的第No短的,No从1开始算 for( k = 1; k <= n; ++k ) //枚举位置i的木棒 ,其长度为k { oldVal = skipped; if( !used[k]) { ++ No; //k是剩下的木棒里的第No短的 if( i == 1 ) skipped += C[n][No][UP] + C[n][No][DOWN]; else { if( k > seq[i-1] && ( i <=2 || seq[i-2]>seq[i-1]))//合法放置 skipped += C[n-i+1][No][DOWN]; else if( k < seq[i-1] &&(i<=2 || seq[i-2]<seq[i-1])) //合法放置 skipped += C[n-i+1][No][UP]; } if( skipped >= cc ) break; } } used[k] = true; seq[i] = k; skipped = oldVal; } for( int i = 1; i <= n; ++i ) if( i < n) printf("%d ",seq[i]); else printf("%d",seq[i]); printf("\n");}int main(){ int T,n; long long c; Init(20); scanf("%d",&T); while(T--) { scanf("%d %lld",&n,&c); Print(n,c); } return 0;}
- poj1037(dP+排列计数)
- poj1037 dp +排列计数
- poj1037 DP
- 【DP】poj1037
- 洛谷P3672(排列计数dp)
- ZOJ 3725 Painting Storages(DP解排列计数)
- ZOJ 3725 Painting Storages(DP解排列计数)
- poj 1037 dp+排列计数(美妙的栅栏)
- POJ 1037 A decorative fence(dp+排列计数)
- [BZOJ2111][ZJOI2010]排列计数(DP+组合数)
- POJ1037:A decorative fence(DP)
- poj1037
- ZOJ 3725 Painting Storages DP+排列计数
- CS 400 Restricted Permutation 排列,DP计数
- 动态规划入门(四)DP 基本思想 具体实现 经典题目 POJ1160 POJ1037
- Poj1037 A decorative fence(DP好题)
- hdu5116(dp + 计数)
- HDU4055 (dp计数)
- 看看虾子怎么好吃
- Junit测试框架
- Ibatis大于,小于等于
- 使用jquery .ajax()的jsonp跨域访问
- Activity的Launch mode 以及Intent的setFlags
- poj1037(dP+排列计数)
- hibernate 操作工具类
- 测试题3
- POJ 1363
- 面试4---集合对比
- 《C Primer Plus》 学习笔记系列之(四)
- 我跟SAP那点事(四)
- 手机app
- 两年未更新博客了