[ダイナミックプログラミング]羅区P1282のドミノ
制限時間:1秒 メモリ制限:128メガバイト
タイトル説明
ドミノ上下二つのブロックは、各ブロックは1〜6点を有します。既存のラインアップ
上記ブロック内の点の数とS1、ブロック内の点の数として示され、S2、差それらと呼ば| S1-S2 |。例えば、図8-1において、S1 = 6 + 1 + 1 + = 9 1、S2 = 1 + 5 + 3 + 2 = 11、| S1-S2 | = 2。2つの上側および下側ブロックのスワップ位置するように各Dominoは、180°回転させることができます。ドミノは、ポイントの最小数の上下の行の間の差の回転数の最小値を使用するようにプログラムされています。
図面において、例えば、限り180°回転させる最終的なドミノとして、上下の行の差が0点であることを確認することができます。
入力形式
入力ファイルの最初の行は、正の整数n(1≤n≤1000)であるドミノドミノの数を表します。Nは、N点のドミノの次の行を表します。各行はスペースで区切られた2つの正の整数を有し、垂直ボックスは、ドミノ・ポイントを表し、Bに、及び1≤a、b≤6。
出力フォーマット
出力ファイルのみ1行は、整数が含まれています。これは、得られた回転数の最小値を表します。
サンプル入力と出力
入力#14
6 1
1 5
1 3
1 2
1
考え
私たちは、あなたがドミノの数字を変更することはできませんので、それぞれのドミノは、それらの間のゼロの差として見ることができ、各ドミノのために、分析し、最も時間件名を見た後、明らかにバックパックです問題。
数が理にかなっている各ドミノ2の唯一の違い上下ために、私たちは唯一の[i]が、その上に2つの数のそれらの差を保存するために使用し、それをオンにしていないが、[i]は、それは、[I] -aをONにします。
我々は、セットF [I] [j]は最初のi-ドミノフリップjの最小数のためであり、それは明らかなように、F [i]は[J] = [I-1] [JA [I]、F F分{ [I-1] [J + [I] + 1}。
しかし、計算プロセスは、必然的に1000年* REを防ぐために、我々はその最小値を計算し、それは、-5、ネガティブ発生しますので、私たちはこのように、負の添字の問題を避け、すべてのJプラス5000を持っています。
DP [n]を超える最後のスイープ[j]は、あなたが最適解を見つけることができます!
いくつかの単語の男は、コードにしました
#include <アルゴリズム>
の#include <iostreamの>
する#include <cstdioを>
する#include <cmath>
使用して名前空間std。
【1010】[10020] F INT。
[1010] int型。
int型のn;
INTメイン()
{
scanf関数( "%のD"、&N);
以下のために(INT i = 1; iが++; iが<= N)
{
int型X、Y。
scanf関数( "%dの%のD"、およびX&Y)。
[i]は、XYを=。
}
ため(; iがn = <; I = 0がint型I ++)
のための(INT J = 1; J <= 10015; J ++)
F [i]は[J] = 0x3f3f3f3f。
F [0] [+ 5010 0] = 0;
(I ++; iが<= N I = 1 INT)のため
のために(J ++ INT J = 10; J <= 10010)
[I] JA] [I] [J] F =分([I-1] F 、F [I-1] [J + [I] + 1)。
int型のTEMP = 0x3f3f3f3f、ANS = 0x3f3f3f3f。
IF(F [N] [i]は!= 0x3f3f3f3f)
{
IF(ファブ(I-5010)<= TEMP)
{
IF(ファブ(I-5010)== TEMP)
ANS =分(ANS、F [n]は[I])。
TEMP =ファブ(I-5010)。
ANS = F [N] [i]は、
}
}
のprintf( "%d個の\ n"、ANS)。
0を返します。
}