拔河 動態規劃 BOJ 216

2021-08-25 02:58:56 字數 2957 閱讀 9353

乙個學校舉行拔河比賽,所有的人被分成了兩組,每個人必須且只能夠在其中的一組,要求兩個組的人數相差不能超過1,且兩個組內的所有人體重加起來盡可能地接近。 輸入n

n

,和n'>n

n個整數wi

w

i代表每個人的體重。輸出兩個整數,分別代表兩組的體重之和。

3

100 90 200

190 200
n≤

100.

n

≤100.

∀i,wi≤

450.

∀ i,

wi

≤450.

首先考慮貪心,發現顯然不可行。因而考慮動態規劃。

先來考慮該問題是否有最優子結構。對於前

i i

個人而言,若有一種分組方法使得

i'>i

i個人的體重可以盡量平均分成兩組,我們也無法通過此結果求出前i+

1 i+1

個人的最優分組,無法進行狀態轉移。

我們顯然可以通過存在性求解出最優解。也就是說,如果可以得知選擇

j j

個人能否使他們體重和為

k'>k

k,我們便可以求出答案。對於這個存在性問題,便可以使用動態規劃求解了。此題wi

w

i較小,可以將體重和作為乙個狀態,令 dp

(i,j

,k) dp(

i,j,

k)

表示在前

i i

個人中選擇

j'>j

j個人能否使得他們的體重和為

k k

,轉移方程為dp

(i,j

,k)=

dp(i

−1,j

−1,k

−wi)

||dp

(i−1

,j,k

)'>dp(

i,j,

k)=d

p(i−

1,j−

1,k−

wi)|

|dp(

i−1,

j,k)

dp(i

,j,k

)=dp

(i−1

,j−1

,k−w

i)||

dp(i

−1,j

,k)。求出dp陣列後,選擇使dp

(n,n

2,k)

=tru

e dp(

n,n2

,k)=

true

成立的最靠近∑i

wi2 ∑iw

i2

的k k

值即為答案。

實現時,要注意

n'>n

n能否被2整除,還可以對dp陣列進行滾動,減少一維空間複雜度,具體細節見**。

狀態共有n2

∑iwi

n 2∑

iw

i個,可在θ(

1)θ (1

)時間內完成狀態轉移,最終求出答案複雜度為θ(

∑iwi

) θ(∑

iwi)

總時間複雜度為θ(

(n2+

1)∑i

wi) θ((

n2+1

)∑iw

i)

#include

using

namespace

std;

#define gt() getchar()

const

int maxn = 100 + 7;

const

int maxw = 450 + 7;

bool dp[maxn][maxn*maxw] = ;

int w[maxn];

int n;

int read()

return res;

}int main()

dp[0][0] = true;

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

for(int j = i; j >= 1; --j)

for(int k = sum; k >= w[i]; --k)

dp[j][k] = dp[j - 1][k - w[i]] | dp[j][k];

int ans = 0;

int p;

for(p = sum>>1; dp[n/2][p] == false; --p);

ans = max(p, ans);

if(n % 2 == 1)

printf("%d %d\n", ans, sum - ans);

return

0;}

0-1揹包問題中,限制了揹包的最大重量。事實上,可以通過0-1揹包限制任何條件。通過0-1揹包,可以求解在最大價值一定時的最大重量,可以求解最大價值一定時的最大價值。

在本題中,可以在限制最大體重和時求出最大體重,即在

n n

個人中各選出若干個人使得其體重總和在不超過∑i

wi2'>∑iw

i2∑i

wi2時的最大值,是否就是答案呢?

顯然不是。這個演算法只保證了將

n n

個人的體重盡量均分,但是沒***人數均分。

可以寫出一組資料證明該演算法的錯誤性:

input:

6

20 28 13 13 13 13

對於該演算法,會輸出48 52,但正確答案應為46 54

boj 216

貪心演算法不顯然正確且資料範圍較小的最優解問題中,均可考慮動態規劃。

動態規劃不僅可以解決最優解問題,還可以解決存在性問題。對於難以直接求出最優解的問題,可以轉換為存在性問題進行求解。

動態規劃21

如下所示的由正整數數字構成的三角形 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 從三角形的頂部到底部有很多條不同的路徑。對於每條路徑,把路徑上面的數加起來可以得到乙個和,和最大的路徑稱為最佳路徑。你的任務就是求出最佳路徑上的數字之和。注意 路徑上的每一步只能從乙個數走到下一層上和它最...

動態規劃 2 1

public intcrosssum int nums,int left,int righ,int p int rightsubsum integer.min value currsum 0 for int i p 1 i i return leftsubsum rightsubsum public...

PID72 拔河比賽 (動態規劃)

題目描述 superwyh的學校要舉行拔河比賽,為了在賽前鍛鍊大家,老師決定把班裡所有人分為兩撥,進行拔河因為為鍛鍊所以為了避免其中一方的實力過強老師決定以體重來劃分隊伍,盡 量保持兩個隊伍的體重差最少,因為老師對結果沒興趣,所以只告訴老師最小的體重差是多少就行了。這個受苦受累的任務就交給super...