【動態規劃】搭建雙塔
阿新 • • 發佈:2019-02-06
描述 Description | |
2001年9月11日,一場突發的災難將紐約世界貿易中心大廈夷為平地,Mr. F曾親眼目睹了這次災難。為了紀念“9?11”事件,Mr. F決定自己用水晶來搭建一座雙塔。
Mr. F有N塊水晶,每塊水晶有一個高度,他想用這N塊水晶搭建兩座有同樣高度的塔,使他們成為一座雙塔,Mr. F可以從這N塊水晶中任取M(1≤M≤N)塊來搭建。但是他不知道能否使兩座塔有同樣的高度,也不知道如果能搭建成一座雙塔,這座雙塔的最大高度是多少。所以他來請你幫忙。 給定水晶的數量N(1≤N≤100)和每塊水晶的高度Hi(N塊水晶高度的總和不超過2000),你的任務是判斷Mr. F能否用這些水晶搭建成一座雙塔(兩座塔有同樣的高度),如果能,則輸出所能搭建的雙塔的最大高度,否則輸出“Impossible”。 |
輸入格式 Input Format | |
輸入的第一行為一個數N,表示水晶的數量。第二行為N個數,第i個數表示第i個水晶的高度。 |
輸出格式 Output Format | |
輸出僅包含一行,如果能搭成一座雙塔,則輸出雙塔的最大高度,否則輸出一個字串“Impossible”。 |
樣例輸入 Sample Input | |
樣例輸出 Sample Output | |
來源 Source |
|
某校NOIP模擬題 |
揹包變形。傳統揹包加一維狀態。
f[j1,j2]表示對於前i個水晶,能不能構成高度分別為j1,j2的塔
f[j1,j2]=f[j1-v[i],j2] or f[j1,j2-v[i]] or(f[j1,j2])
最後從大到小列舉i,若f[i,i]=true 則輸出i 結束程式
最後輸出 ‘Impossible'
注意i的下界不是0而是1
注意輸出 'impossible'
var i,j1,j2,n,max,s:longint; v:array[1..100]of longint; f:array[-1000..1000,-1000..1000]of boolean; begin fillchar(f,sizeof(f),false); readln(n); for i:=1 to n do read(v[i]);s:=0; for i:=1 to n do s:=s+v[i]; max:=s div 2; f[0,0]:=true; for i:=1 to n do for j1:=max downto 0 do for j2:=max downto 0 do f[j1,j2]:=(f[j1-v[i],j2])or(f[j1,j2-v[i]])or(f[j1,j2]); for i:=max downto 1 do if f[i,i] then begin writeln(i); exit; end; writeln('Impossible'); readln;readln; end.