動態規劃 貓狗大戰(揹包)

2022-07-20 23:57:19 字數 2139 閱讀 4035

第二題

描述 description

新一年度的貓狗大戰通過sc(星際爭霸)這款經典的遊戲來較量,野貓和飛狗這對冤家為此已經準備好久了,為了使戰爭更有難度和戲劇性,雙方約定只能選擇terran(人族)並且只能造機槍兵。

比賽開始了,很快,野貓已經攢足幾隊機槍兵,試探性的發動進攻;然而,飛狗的機槍兵個數也已經不少了。野貓和飛狗的兵在飛狗的家門口相遇了,於是,便有一場腥風血雨和陣陣慘叫聲。由於是在飛狗的家門口,飛狗的兵補給會很快,野貓看敵不過,決定撤退。這時飛狗的兵力也不足夠多,所以沒追出來。

由於不允許造醫生,機槍兵沒辦法補血。受傷的兵只好忍了。555-

現在,野貓又攢足了足夠的兵力,決定發起第二次進攻。為了使這次進攻給狗狗造成更大的打擊,野貓決定把現有的兵分成兩部分,從兩路進攻。由於有些兵在第一次戰鬥中受傷了,為了使兩部分的兵實力平均些,分的規則是這樣的:1)兩部分兵的個數最多只能差乙個;2)每部分兵的血值總和必須要盡可能接近。現在請你編寫乙個程式,給定野貓現在有的兵的個數以及每個兵的血格值,求出野貓按上述規則分成兩部分後每部分兵的血值總和。

輸入格式 input format

第一行為乙個整數n(1<=n<=200),表示野貓現在有的機槍兵的個數。以下的n行每行乙個整數,表示每個機槍兵的血格(1<=ai<=40)。

輸出格式 output format

只有一行,包含兩個數,即野貓的每部分兵的血值總和,較小的乙個值放在前面,兩個數用空格分隔。

樣例輸入 sample input

樣例輸出 sample output

35 52

時間限制 time limitation

各個測試點1s

分析揹包問題的變形

首先要正確理解題意:分成兩隊人,人數最多相差1,就是要把總人數均分,一隊為n div 2,另一對為n-n div 2

用搜尋的話,只需列舉構造一兵的情況即可,總的狀態數大約為c(n)(n div 2),前兩組資料都可以搜過,資料中還有一種特殊情況,就是所有兵的攻擊力相同。如果騙分程式的話,最多可得30分。

正解當然是動態規劃。

如果我們將選擇的人數也看成一種體積的話,之後類似裝箱問題,將最優性問題轉化為判定性問題,可以寫出下面的方程:

f[i,j,k]表示前i個人中選了j個人,能否達到k的攻擊力。為boolean型別

f[i,j,k]:=f[i-1,j,k] or f[i-1,j-1,k-a[i]]

顯然之和第i個人選不選有關,所以說是揹包問題的變形。如果是三維的方程,由題目中的資料範圍大概是200*100*40*200(注意,題目中特別強調最大攻擊力是有提示性的,給出了k迴圈的上界(j*40),大約305mb(高二的小盆友會算記憶體嗎?)

毫無選擇,必須優化。根據0/1揹包的原理,我們可以壓縮一維狀態:

f[j,k]:=f[j,k] or f[j-1,k-a[i]]

當然j和k都需要倒序迴圈!

計算一下時間複雜度,大約是10^7

這道題不是很難,基本符合noip的要求,但是需要一定的思維量和對揹包問題的深刻理解。

program liukeke;

var a:array[1..200] of longint;

f:array[0..200,0..8000] of boolean;

n,i,sum,k,j,n2:longint;

begin

readln(n);

for i:=1 to n do

begin

readln(a[i]);

inc(sum,a[i]);

end;

n2:=n div 2;

f[0,0]:=true;

for i:=1 to n do

for j:=n2 downto 0 do

for k:=j*40 downto a[i] do

f[j,k]:=f[j,k] or f[j-1,k-a[i]];

for i:=(sum div 2) downto 0 do

if f[n2,i] then

begin

write(i,' ',sum-i);

break;

end;

end.

反思這道題中的揹包是抽象的,要抽象出一維體積,將問題完美的轉化為二維揹包。

有時,最優性問題很難求解,要把最優性問題轉化成判定性問題。

kaggle貓狗大戰

kaggle貓狗大戰 kaggle上的貓狗大戰,即對貓狗的分類 沒有特徵資料,只有,所以只能運用神經網路對其訓練 看了大量的kaggle上的公開例子,大多運用tensorflow或者keras建立神經網路,因為最近在學習torch,因此,想用torch建立卷積神經網路進行建模 但整個過程遇到了很多坑...

洛谷 貓狗大戰

初見安 這裡是傳送門 洛谷p1489 貓狗大戰 乙個挺冷門的題啊 也蠻有意思的。把n個數劃分成兩部分,讓兩部分的數的總和的差值盡量小。其實一眼dp,但是要往正解的方向去想是有點點難度的 明顯我們確定乙個集合,另乙個集合也就可以確定了。思考暴力一點的做法 如果我們可以列舉乙個集合的所有可能性,是不是就...

動態規劃 揹包

揹包經典問題 揹包問題01 乙個揹包容積為t 0 t 2000 現在有n 0 如下 includeusing namespace std int s 1005 bool f 3000 int main 揹包問題02 若每種物品有無限多個。從這n種物品中選取若干個裝入揹包內,使揹包所剩的空間最小。請求...