洛谷 P1282 多公尺諾骨牌 (揹包dp)

2021-09-30 13:35:39 字數 1663 閱讀 4166

題目描述

多公尺諾骨牌有上下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行點數之差達到最小。

6 1 1 1

1 5 3 2

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

輸入輸出格式

輸入格式:

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

輸出格式:

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

輸入輸出樣例

輸入樣例#1:

4 6 1

1 5

1 3

1 2

輸出樣例#1: 1

動態規劃不解釋(然而luogu的dalao有好多其他方法)。本蒟蒻剛開始用的是遞迴,結果tle/ac=4/7(共11個點),36分。(為啥先用遞迴? 因為個人覺得好理解啊)

但是記憶化搜尋又不太會用,所以就轉成迴圈.

i:前i個骨牌

j:前i個骨牌上下方塊點數的差

c[i][j] 表示前i個骨牌上下方塊點數差為j的最小旋轉次數(所以是min)

d[i]為第i個骨牌上下方塊點數的差

以下貌似並不是很重要的樣子:

程式設計用最少的旋轉次數使多公尺諾骨牌上下2行點數之差達到最小。差達到最小優先於旋轉次數最小,所以從 差為0 開始向正負兩側同時尋找,第乙個找到的即為最優解(當然正負側同時找到時,需要再做比較)

多公尺諾骨牌點數為1~6,所以單個骨牌的差最大為6-1=5;骨牌數n≤1000,所以上下之差 -5000<=j<=5000

(c++的陣列下標是負數時好像會出現什麼奇怪的東西,所以為了保險起見,做了一些改動)

下面附上**:

#include

#include

using

namespace

std;

int a[1002]=,b[1002]=,d[1002]=;

int c[1002][10001]=;

int min(int a,int b)

int main()

k=1002;

c[0][5000]=0;

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

for(j=-5000;j<=5000;j++)

c[i][5000+j]=min(c[i-1][5000+j-d[i]],c[i-1][5000+j+d[i]]+1); //<-狀態轉移方程

j=5000;

while(j<10000)

cout

0;}

(蒟蒻第一次寫,勿噴)

洛谷 P1282 多公尺諾骨牌

題目描述 多公尺諾骨牌有上下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多公尺諾骨牌

多公尺諾骨牌有上下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多公尺諾骨牌

大佬的思路 這其實是一道 披著狼皮的揹包題 我們只需要對狀態稍作調整就可以套揹包啦 我們先把骨牌翻轉,調整至點數大的在上面 這樣,我們就能保證上方的點數一定比下方大,並且保證每翻轉一 次,都能使上下的點數之差變小,而變小的點數,就是上下點數之差乘以2。把改變的點數看成物品的體積,初始上下方的點數之差...