フェンスで囲まれた木材のN-1 Nのブロックの長さ。フェンスの要件は、その側面のいずれかより高いボード(高)よりも(低い)低いより即ち各ボード又は基板の両面、波打っています。今の要件を満たすために、すべての手配を並べ替えます。照合は、短いランキング越前、木材の最初の部分から、前の、比較的後方ターンに等しい計算されます。(すなわち、辞書式順序)が最初に与えられ、指定された数N mは、m番目の配置の要件の遵守を求めます。
入力:最初の行は、テストケースの正の整数の数を示します。各行はそれぞれ、2つの数Mを含むテストケースを取り、N表します。
出力:木製指定された順列スキーム。ケースのすべてについて、N = 4のために示されているように
、サンプルインプット
2
2 1
3 3
サンプル出力
1 2
2 3 1
まず、乗数最適化DPと同様に、我々は木製のフェンスの長さcのためのランキングを決定するために法律でいっぱいにしてみてください。
まず、我々はHに、合計n-1個のプログラムが設定数tバック厚板、木材の最初のブロックの長さを列挙することができ、
T> = Cあれば、長さの木の最初のブロックは、Hであり、決定しようとし続けます木材の第2のブロックの長さ、またはC = Tは、Hは、上記の決意を繰り返す1だけインクリメントされます。
何、その後、(そこそこ)、我々は答えを見つけることができ、我々は今トンのための前処理値を必要とします
F [I、J、K]はiが状態kで異なるボードフェンス、大j番目のビットに小さいから左端ボードを構築ブロック長を示す設定(kは低い0であり、kは1が高い示す図です)
F [I、J、0] =ΣP= J〜I-1F [I-1、P 1]
F [I、J、1] =ΣP= 1〜J-1F [I-1、P、 0]
長い 長い F [ 21 ] [ 21 ] [ 2 ]、M。 BOOL使用[ 21 ]。 ボイド)(調製 { int型I、J、K。 F [ 1 ] [ 1 ] [ 0 ] = F [ 1 ] [ 1 ] [ 1 ] = 1 。 用(i = 2、iは<= 20 ; iは++ ) のために(J = 1 ; J <= I; J ++ ) { ため(K = J、K <= I- 1 ; ++ K)F [i]は[J] [ 0] + = F [I- 1 ] [K] [ 1 ]。 用(k = 1 ; kは<= J- 1 ; kは++)F [i]は[J] [ 1 ] + = [I-F 1 ] [K] [ 0 ]。 } }
次の開始テストを満たすために、木材の最終長片、Kの高さ位置、呼ば
; K ^ = 1:1
iは、判断、決定されたLENを識別する長さlenの列挙:2
3:Iプラス1、。繰り返しの手順
書式#include <iostreamの> の#include <cstdioを> する#include <CStringの> の#include <cmath> の#include <アルゴリズム> 書式#include <キュー> 使用して 名前空間はstd; 長い 長い F [ 21 ] [ 21 ] [ 2 ]、M。 BOOL使用[ 21 ]。 ボイド)(調製 { int型I、J、K。 F [ 1 ] [ 1 ] [ 0 ] = F [ 1 ] [ 1 ] [ 1 ] = 1 。 にとって(I = 2 ; iが= < 20 ; iは++ ) のために(J = 1 ; J <= I; J ++ ) { ため(K = J、K <= I- 1 ; ++ K)F [i]は[J] [ 0 ] + = F [I- 1 ] [K] [ 1 ]。 用(k = 1 ; kは<= J- 1 ; kは++)F [i]は[J] [ 1 ] + = [I-F 1 ] [K] [ 0 ]。 } } int型のmain() { int型、T、N、I、J、K、最後に、LEN。 scanf関数(" %のD "、&T)。 準備()。 一方、(t-- ) { scanf関数(" %Dの%のLLD "、&N、&M)。 memsetの(使用、0、はsizeof (使用されます))。 用(J = 1 ; J <= N; J ++)// 第一块木板单独处理 { 場合(F [N] [J] [ 1 ]> = M) { 最後 = J、K = 1 。 破ります; } 他 M- = F [N] [J] [ 1 ]。 もし(F [N] [j] [ 0 ]> =M) { 最後 = J、K = 0 。 破ります; } 他 M- = F [N] [j] [ 0 ]。 } [最終]使用 = 1のprintf(; " %のD " 、最後); 以下のための(I = 2 ; iが<= N; iは++ ) { K ^ = 1 ; J = 0 。 用(LEN = 1 ; LEN <= N; LEN ++ ) { 場合(使用[LEN])続けます。 J ++ ; もし((k個の== 0 && LEN <最後)||(k個の== 1 && LEN>最後))// 合法性 { 場合(F [N-I + 1 ] [j] [k]が> = M){最後= LEN; ブレーク;} そう M- = [N-I + F 1 ] [j] [k]は、 } } [最終]使用 = 1 。 printf(" %d個" 、最後の); } プット("" )。 } 戻り 0; }