◦ ftiasch 有 n 個物品, 體積分別是 w1, w2, ..., wn。 由於她的疏忽, 第 i 個物
品丟失了。 「要使用剩下的 n - 1 物品裝滿容積為 x 的揹包,有幾種方法
呢?」 -- 這是經典的問題了。
◦她把答案記為 count(i, x) ,想要得到所有1 <= i <= n, 1 <= x <= m的 count(i,
x) **。
◦ n,m<=3000
題解
◦設f[x]表示全部物品都可用恰好裝滿x體積時的方案數,可以用01揹包演算法
求出。這是總方案數。
◦然後考慮不選某物品的情況。
◦設g[x]為不選當前物品恰好裝滿x體積時的方案數。
f[i]加進去當前物品, g[i]不加
f[i]=f[i]+f[i-w[i]]
f[i]=g[i]+g[i-w[i]]
g[i]=f[i]-g[i-w[i]]
◦當x小於w[i]時, i物品一定不會被選上 g[i]=f[i]。
◦當x大於等於w[i]時, i物品可能會被選上,直接求不選的情況比較困難。
◦總方案數及f[x],不選的方案數可以想為先不選i再最後把i選上,即g[x-w[i]]。
◦所以g[x]=f[x]-g[x-w[i]], x從小到大列舉計算g即可。
◦每次都是線性複雜度,一共n次計算,總複雜度是o(n*m)
另兩種理解方式
◦ 1:也可以用生成函式來理解。
◦ 2:直接考慮程式**也可以很簡單的理解。
上面有些晦澀難懂,下面看乙個仍然晦澀難懂的描述
設 f[ j ][ 0 ] 為體積為 j ,第 i 個物品可以選上的時候,體積為 j 的最大方案數
設 f[ j ][ 1 ] 為體積為 j ,第 i 個物品沒選的時候,體積為 j 的最大方案數
假設沒有物品消失,那麼這就相當於乙個01揹包問題,f[ x ][ 0 ] 之間的轉移
如果有物品消失的話,就相當於在原來的方案數上減去它
對於物品 i ,如果當前的體積可以放進去,那麼它就由 選中的方案 - 沒選中的方案,因為之前可能選上了 i (qaq太艱難了)
對於物品 i ,如果當前的體積不能放進去,那麼直接由 f[ x ][ 0 ] 轉移過來,因為在原來的方案裡一定是沒有選中它的
**
#includeusingnamespace
std;
inline
intread()
const
int maxn=2005
;int
n,m;
intw[maxn];
int f[maxn][2
];int
main()
printf("\n
");}
return0;
}
洛谷P4141 消失之物 揹包DP
暴力 暴力列舉少了哪個,下面套乙個01揹包 f i j 表示到了i物品,用了j容量的揹包時的方案數,f i j f i 1 j f i 1 j w i o n 3 優化 不考慮消失的,先跑乙個01揹包,定義g i j 表示i消失時,容量為j的方案數,g i j f n j 不合法的 逆著過來就是g ...
洛谷P4141 消失之物 題解 揹包問題擴充套件
題目大意 有 n 件物品,求第 i 件物品不能選的時候 i 從 1 到 n 0 1揹包方案數。解題思路 遍歷每一遍不選的物品,然後對剩餘的物品求01揹包方案數。時間複雜度為 o n 2m 由於這裡每一件物品的價值和時間相同,所以可以定義狀態 f i 表示填滿體積 i 的方案數。則有狀態轉移方程 f ...
消失之物,分治
ftiasch 有 n 個物品,體積分別是 w1,w2,wn。由於她的疏忽,第 i 個物品丟失了。要使用剩下的 n 1 物品裝滿容積為 x 的揹包,有幾種方法呢?這是經典的問題了。她把答案記為 count i,x 想要得到所有1 i n,1 x m的 count i,x view code 輸入格式...