P1282 多公尺諾骨牌 差值DP 揹包

2022-04-30 10:36:13 字數 1466 閱讀 7861

多公尺諾骨牌有上下2個方塊組成,每個方塊中有1~6個點。現有排成行的

上方塊中點數之和記為s1,下方塊中點數之和記為s2,它們的差為|s1-s2|。例如在圖8-1中,s1=6+1+1+1=9,s2=1+5+3+2=11,|s1-s2|=2。每個多公尺諾骨牌可以旋轉180°,使得上下兩個方塊互換位置。 程式設計用最少的旋轉次數使多公尺諾骨牌上下2行點數之差達到最小。

對於圖中的例子,只要將最後乙個多公尺諾骨牌旋轉180°,可使上下2行點數之差為0。

輸入格式:

輸入檔案的第一行是乙個正整數n(1≤n≤1000),表示多公尺諾骨牌數。接下來的n行表示n個多公尺諾骨牌的點數。每行有兩個用空格隔開的正整數,表示多公尺諾骨牌上下方塊中的點數a和b,且1≤a,b≤6。

輸出格式:

輸出檔案僅一行,包含乙個整數。表示求得的最小旋轉次數。

輸入樣例#1:

4

6 11 5

1 31 2

輸出樣例#1:此題是一道雙向揹包.

這道題一看,就覺得應該和揹包有點關係.然後要想到揹包的本質是什麼.

揹包的本質就是通過當前狀態的前驅, 進行更新.

然後就是狀態定義:

f[ i ][ j ] 表示 前 i 個組合裡面 上面那個陣列的和. 

同時因為無論怎麼變化 兩個數列的總和始終是不變的.

所以之後的狀態轉移方程和 揹包非常相似.

可以試著自己想一想.

ps: 注意 f[1][ ] 的初始化.

**(內有一部分注釋) :

#includeusing

namespace

std;

const

int maxn=1008

;const

int inf=1231654;

intn,a[maxn],b[maxn];

intw[maxn],sum;

int f[maxn][6*maxn]; //

狀態表示 前 i 個裡面上一列的值是多少. //

同時因為交換不會改變兩列數的總和,所以可以很方便地求出另外一列的值

intmain()

//表示 初始狀態. 若第乙個換就是 0 否則為1;

for(int i=1;i<=n;i++)

for(int j=0;j<=n*6+10;j++) f[i][j]=inf;

f[1][a[1]]=0; f[1][b[1]]=1

;

for(int i=2;i<=n;i++)

//注意從 2 開始

for(int j=0;j<=n*6;j++)

int minc=inf,mint=inf;

for(int i=1;i<=sum;i++)

cout

return0;

}

P1282 多公尺諾骨牌 DP

多公尺諾骨牌有上下2個方塊組成,每個方塊中有1 6個點。現有排成行的 上方塊中點數之和記為s1,下方塊中點數之和記為s2,它們的差為 s1 s2 例如在圖8 1中,s1 6 1 1 1 9,s2 1 5 3 2 11,s1 s2 2。每個多公尺諾骨牌可以旋轉180 使得上下兩個方塊互換位置。程式設計...

P1282 多公尺諾骨牌 DP

題目大意 題解當知道 總和 及 單行的和 就可以算出差值的大小 1 2 3 4 單行和l 10 8 7 6 5 總和s 36 則上下行的差值為 l s l include define inf 0x3f3f3f3f using namespace std int n,a 1005 b 1005 dp...

P1282 多公尺諾骨牌 dp,揹包

評測記錄 n個多公尺諾骨牌,上下值不相同,可以交換乙個多公尺諾上下的值,求最少的交換次數使上下之和的差值最小。用f i,j n fi,j n表示只計算前i個多公尺諾,上下之差為j需要的最小次數,然後類似揹包的想法正常用差值轉移就好了。include include include define n ...