問題の説明:
次の規則は、今順番に番号1,2,3、...ボールにn列をYaoanされ、n個の列があるとします。
(1)あなただけの柱の上部にボールを置くことができます。
(2)同じ列に、任意の2個の隣接するボールが完全正方形の数の合計です。
ボールの最大数はn列の上に置くことができる計算するアルゴリズムを設計するようにしてください。例えば、4つの列に11球を保持することができます。
<<プログラミングタスク:
所与のnについて、ボールの最大数を計算するN列に置くことができます。
4 <= N <= 55
問題の解決策
単球が重要ではなく、決意が下に設置いくつかのカラムを必要とするボールに添加することができる場合、列数の増加を考慮すると、増加します。
各ボールは大から小側にも一度だけ確保するために接続されたエッジの数の正方形の周りに互いへの2個のボールが接続され、二つの点に分割しました。
質問は、次に最小のパスカバレッジとなり、パスの数は列の数です。
M個のボール列挙、答えのようなトラバースのパスからの出力にプログラムするように、数m-1カラムよりも大きいパスの数。
タイムアウトしないようにするために、我々は新しいボールを追加し、パスを増大させるから、一度ボールを走った理由を大から小にもエッジにある、ことができます。
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 const int型 MAXN = 3605 ; INTのN、M。 int型VIS [MAXN]、試合[MAXN]、タイマー。 BOOL正方形[MAXN << 1 ]。 ベクター < INT > E [MAXN]。 ボイドのinit(){ タイマ = 0 。 memset(一致、0、はsizeof (一致))。 memsetの(VIS、0、はsizeof (VIS))。 } BOOL DFS(INT U){ 場合(VIS [U] ==タイマー)返す 偽; VIS [U] = タイマー。 用(符号なし整数 = I 0 ; iは<E [U] .size(); iは++ ){ int型、V = E [U] [I]。 もし(!一致[V] || DFS(一致[V])){ 一致[V] = U。 返す 真; } } を返す 偽。 } ボイド GET(INT U){ のprintf(" %dの" 、U)。 VIS [U] = タイマー。 もし(![一致U +1800 ]){のputchar(10)。返す;} 得る(一致[U + 1800 ])。 } ボイドプリント(){ ++ タイマー。 以下のために(int型 I = 1 ; iがm <I ++のが) もし(!VIS [i]を=タイマー)を取得(I); } int型のmain(){ ため(int型 i = 1 ; iは= <* 7200 ; iは++ ) 正方形[iが * I] = 真。 scanf関数(" %のD "、&N) int型ANS = 0 ; 一方、(++ {M) のための(int型 iは= 1 ;私がm <I ++の) 場合(正方形[iがmを+])E [M] .push_back(I + 1800 )。 ++ タイマー; もし(DFS(M))ANS ++ 。 もし(M-ANS> N){のprintf(" %d個の\ n "、M- 1)、印刷();出口(0 );} } }
そこ貪欲法、置く、または新しくオープンした(正しさを知らない)に柱が置くことができます。
一見、法律2 + 2 + 4 + 4 + 6 + 6 +ボールの数があります....