// UVA 1204
そのイタリア:ゲームをプレイ円の中の子供(少なくとも二つ)の一部。各ラウンドは、子供の左または右から自分のハンカチを渡すようになりました。
子供が(最初の子を含む)ハンカチを取得し、彼のハンカチのセックスに書いた、少年はBを書いた、女の子はGを書き、
その後、次の子に渡された同じ方向に、すべての子供がどんなで書くこと丸めます停止後。
今のゲームは、少なくとも数人の子供を求めて、ホイール、ハンカチラウンドに残って知られている単語のn回目のnとなっています。
ハンカチラウンドの番号は100を超えてはなりません。
2 <= N <= 16の
アイデア:我々は最初のリングラインに、問題を単純化することができ、
そしてその後、上記動的プログラミングラインを解決するために、その後輪に変換します。
オンライン質問については、我々は、n個のサブシーケンスを含む配列は、なるように、最短のシーケンスを知りたい
場合、kシーケンスのために、我々は上記のシーケンス、シーケンスのみ(k個の挿入位置の前にk個のkに関連付けられたシーケンスを挿入したいです)その配列の前で
そう、我々は異なる領域(IJ)の状態を含めるために必要なものを最後のシーケンスが含まれるために私たちの状態は、ほとんどの可解性があるもので
、徐々にで、範囲を拡大し、最終的な出力全集(1-n)は最も解けることができ、私たちは= N <= 16 <2のためのコレクションを含む述べる必要があり
、この範囲は単に(ソート、セットが表現されてもよい)であり、最終的な状態を得ることが可能です定義:
D(S、j)をjは、最短配列の要素の端の集合を表します。
第二は、状態遷移式である:
D(S、J)=分(D(S- {J}、I)+ T(J) -両方の(I、J))(両方の(I、J)はIで表されますjは尾部に頭部の公開部分である)
と増加列挙再帰メソッド集合、その後の状態での合計(N * 2 ^ N)について解く、意思決定の(N)種類の各、
このため、時間複雑度はO(N ^ 2 * 2 ^である N)
!それを回転変換する処理のライン(又は行)について話をするには、以下の
(1)タイトルはここで、反時計回りに時計回りに言ってもよいです上記の処理が可能2Nがあるライン、各状態d(i、j)を考慮していないときには、意思決定の数も2n個となり、
これは単に変換定数である私たちは、処理を考えると、時間の複雑さは、変更されませんこれは、「粘着性」または逆オーバー正である「スティッキー。」
(2)第二は、エンドツーエンドの接続公園の特徴を考慮することであるので、我々は終わりと始まりの間の重なりを考慮する公園を扱って、作っている、
寸法を高めるために持っているような、状態の最初の列の配置を知ることが必要です(それは状態の定義に「結合」しなければならない)を扱うことができるようになり、
入力文字列の後、考慮される部分は鳴らないかもしれませんが、結果後のラップの多くの周りに、これは影響しませんし、どのように確認する必要がありますコードは、
計算結果が1であれば、その後、我々は2をエクスポートする必要があります。
背後にある問題を処理するために、次のコードを達成するためのコードが(ない場合もある)と言うかもしれないです。
補足(コードハンドルと場所を言うのを忘れて)
共謀最初の場所の問題に対処する方法1.、私は思った、または最初のシーケンスの増加を記録するために何が、第一の配列の方向を決定していない(または彼は唯一の言った
ように、なぜ、それについて考え、最適なソリューションを失わない()1行に1つの方向を、そのコードが、私は唯一の正の方向を提供して?)。
2。
次に、(数学記号を戦うためにも、意志、ハハ)、その後、我々はi∈j単純化された、私は入力の話を、私は二つの配列与えられた場合には、jの間に何かがあるでしょう私は、考えて検討する必要がありますなぜ、その問題を簡素化することができますいくつかのアイデアを思い付くために私たちを促しました。
:コードを書くことで、私は彼がの問題とLRJ解決するためのアイデアについては、次の話を達成することができませんでしたいくつかの問題見つかっ
1が他が含まれている2つの入力のシーケンスを決定する方法を、1?find関数で文字列のSTLを使用してください。
2.なぜセクションが始まる記録に次元を追加する必要はないかもしれませんか?ラインシーケンスの先頭に正の方向を、必要に応じて。(ですから、最適なソリューションを失うことはありません?それについて考え、なぜ?)
3、シーケンスのための解決方法の周りに数周することができますか?これは時間の終わりに「スティック」(私は非常に明確ではないと思われた)最後の最後に反映されます。
ここで達成するためのコードは次のとおりです。
// UVA 1204 の#include <cstdioを> する#include <CStringの> の#include <iostreamの> の#include <アルゴリズム> 書式#include < 文字列 > 使用して 名前空間はstd; #define REP(I、N)(I = 0をint型、iが(N)<; ++ i)はのためのconst int型 MAXN = 16 。int型 calc_overlap(CONST 文字列&、CONST 文字列&B){ int型 N1 = a.length()。 INT N2 = てb.length()。 以下のための(int型私は= 1 ; 私は、N1 <; ++ I){ 場合(N2 + iは= N1 <)続けます。 BOOL = OK 真。 以下のための(int型 J = 0 ++; J + iのN1 < j)の 場合(![J + I] = B [J]){OK = 偽 ; 破ります; } 場合(OK)を返す N1- I。 } 戻り 0 。 } 構造体の配列{ ストリングS、REV。 ブール 演算子 <(constの配列&RHS)CONST { 戻り s.length()< rhs.s.length()。 } }配列[MAXN]。 int型のn; ストリング NEW_SEQ [MAXN] [ 2 ]。 int型のlen [MAXN]。 INTオーバーラップ[MAXN] [MAXN] [ 2 ] [ 2 ]。 無効INITを(){ REP(I、N){ CIN >> 配列[i]は.S。 配列[i]は.rev = 配列[i]は.S。 リバース(配列[I] .rev.begin()、配列[i]の.rev.end())。 } INT N2 = 0 。 ソート(配列、配列 + N) REP(I、N){ BOOL=必要に真。 用(int型 J = I + 1、J <N; ++ J){ もし(配列[J] .s.find(配列[I] .S)=!文字列 ::のNPO || 配列[J] .rev。見つける(配列[I] .S)!= 文字列 :: NPO等){必要= 偽 ; 破ります; } } もし(必要){ NEW_SEQ [N2] [ 0 ] =配列[i]は.S。NEW_SEQ [N2] [ 1 ] = 配列[i]の.rev。 LEN [N2] = 配列[I] .s.length()。 N2 ++ ; } } N = N2。 REP(I、N)REP(J、N)REP(X、2)REP(Y、2 ) オーバーラップ[I] [J] [X] [Y] = calc_overlap(NEW_SEQ [I] [X]、NEW_SEQ [ J] [Y])。 } int型の D [ 1 << MAXN] [MAXN] [ 2 ]。 ボイド更新(INT&X、INT V){ 場合(X < 0 || V <x)は、x = V。 } ボイドは(){解く のmemset(D、 - 1、はsizeof (D))を、 D [ 1 ] [ 0 ] [ 0 ] = LEN [0 ]。 INTフル=(1 << N) - 1 。 用(INT S = 1 ; S <フル; ++ S) REP(I、N)REP(X、2)もし(D [S] [I] [X]> = 0 ) のための(INT J = 1。 J <N; ++ j)の 場合((S&(!1 << )J)) REP(Y、2)更新(D [S |(1 << J)] [J] [Y]、D [S ] [I] [X] + LEN [J] - 重なり[I] [J] [X] [Y])。 int型 ANS = - ;1つの。 REP(I、N)REP(X、2 ){ 場合(D [フル] [I] [X] < 0)続けます。 アップデート(ANS、D [フル] [I] [X] -overlap [I] [ 0 ] [X] [ 0 ])。 } 場合(ANS <= 1)ANS = 2 。 printf(" %d個の\ n " 、ANS)。 } int型のmain(){ 一方(scanf関数(" %のD "、&N)== 1個の && N){ INIT()。 解決する(); } 戻り 0 }