拔河比赛
題意
一個學校舉行拔河比賽,所有的人被分成了兩組,每個人必須(且只能夠)在其中的一組,要求兩個組的人數相差不能超過1,且兩個組內的所有人體重加起來盡可能地接近。 ?
分析
這道題目不滿足動態規劃最優子結構的特性。因為最優子結構要求一個問題的最優解只取決于其子問題的最優解。就這道題目而言,當前n-1個人的分組方案達到最優時,并不意味著前n個人的分組方案也最優。但題目中標注出每個人的最大體重為450,這就提醒我們可以從這里做文章,否則的話,命題者大可把最大體重標注到長整型。假設w[i]表示第i個人的體重。f[i,j,k]表示在前i個人中選j個人在一組,他們的重量之和等于k是否可能。顯然,f[i,j,k]是boolean型,其值為true代表有可能,false代表沒有可能。那f[i,j,k]與什么有關呢?從前i個人中選出j個人的方案,不外乎兩種情況:⑴第i個人沒有被選中,此時就和從前面i-1個人中選出j個人的方案沒區別,所以f[i,j,k]與f[i-1,j,k]有關。⑵第i個人被選中,則f[i,j,k]與f[i-1,j-1,k-w[i]]有關。綜上所述,可以得出:
f[i,j,k]=f[i-1,j,k] or f[i-1,j-1,k-w[i]]。
這道題占用的空間看似達到三維,但因為i只與i-1有關,所以在具體實現的時候,可以把第一維省略掉。另外在操作的時候,要注意控制j與k的范圍(0<=j<=i/2,0<=k<=j*450),否則有可能超時。
這種方法的實質是把解本身當作狀態的一個參量,把最優解問題轉化為判定性問題,用遞推的方法求解。這種問題有一個比較明顯的特征,就是問題的解被限定在一個較小的范圍內,如這題中人的重量不超過450。
var
n,i,j,k,n2,t,tj,min:longint;
f:array[0..50,0..450*50]of boolean;
w:array[0..100]of longint;
begin
? ? readln(n);
? ? tj:=0;n2:=(n+1) div 2;
? ? for i:=1 to n do
? ? begin
? ? ? ? readln(w[i]);
? ? ? ? tj:=w[i]+tj;
? ? end;
? ? fillchar(f,sizeof(f),0);
? ? f[0,0]:=true;
? ? for i:=1 to n do
? ? for j:=n2-1 downto 0 do
? ? for k:=450*i downto 0 do
? ? if f[j,k] then f[j+1,k+w[i]]:=true;
? ? min:=maxlongint;
? ? t:=0;
? ? for i:=0 to n2*450 do
? ? if (f[n2,i]=true)and(abs(tj-i-i)<min) then
? ? begin
? ? ? ? min:=abs(tj-i-i);
? ? ? ? if i<=tj div 2 then t:=i else t:=tj-i;
? ? end;
? ? write(t,' ',tj-t);
end.
轉載于:https://www.cnblogs.com/YYC-0304/p/9500161.html
總結
- 上一篇: 大厅安排(normal)
- 下一篇: 叠放箱子问题