Yurchiu's Blog

求方案类背包问题题解 I

Yurchiu 2020-01-24, 17:52:13 661 隐藏左右两栏 展示左右两栏

本文为大型题解集

X1291 数字组合
X1273 【例9.17】货币系统
P1077 摆花

X1291 数字组合

01背包求方案数。here

初探

定义状态:fi,jf_{i,j}表示前ii个数总和为jj的方案数。

那么,对于一个物品,只有选与不选两种情况(当然费用比承重大一定不选)。

易得状态转移方程:

fi,j={fi1,j+fi1,jwiwij fi1,jwi>jf_{i,j}=\begin{cases} f_{i-1,j}+f_{i-1,j-w_i} & w_i\le j \\\ f_{i-1,j} & w_i>j \end{cases}

即,前ii个数总和为jj的方案数与前i1i-1个数有关。前ii个数总和为jj的方案数为前i1i-1个数总和为jj的方案数与前ii个数总和为jwij-w_i的方案数之和。即不入选这个数字与入选这个数字的方案数之和,加法原理。

初始化:前00个数总和为00的方案数为一(只有什么也不选)。

CODE:

f[0][0]=1;
for(int i=1;i<=n;i++)
	for(int j=0;j<=m;j++)
	{
		if(a[i]<=j)
			f[i][j]+=f[i-1][j-w[i]];
		f[i][j]+=f[i-1][j];
	}

时间复杂度与空间复杂度皆为O(nm)O(nm)

优化

ii个数总和为jj的方案数与前i1i-1个数有关。

因此,可以对此优化,直接滚动成一维,把ii的那一维消掉。

CODE:

f[0]=1;
for(int i=1;i<=n;i++)
	for(int j=m;j>=w[i];j--)
		f[j]+=f[j-w[i]];

空间复杂度降为O(m)O(m)

注意,内层循环要逆序。这和01背包的逆序原因类似。

X1273 【例9.17】货币系统

完全背包求方案数。here

与完全背包类似,内层循环改为正序即可。这和完全背包的正序原因类似。

CODE:

f[0]=1;
for(int i=1;i<=n;i++)
	for(int j=w[i];j<=m;j++)
		f[j]+=f[j-w[i]];

P1077 摆花

here

这是个分组背包!为什么呢?

为了在门口展出更多种花,规定第ii种花不能超过aia_i盆,摆花时同一种花放在一起。

ii种花可以放不超过aia_i盆的任意盆。相当于第ii组花有许多捆在一起的花,标号11aia_i。第jj号有jj盆花捆着。每组中的花只能选一个。

f[0]=1;
for(int i=1;i<=n;i++)
	for(int j=m;j>=0;j--)
		for(int k=1;k<=a[i];k++)//标号1至a_i
			if(j>=k)
			    f[j]+=f[j-k];//第j号有j盆花捆着




本文作者:Yurchiu

本文链接:https://yz-hs.github.io/dd819f9a09a1/

版权声明:本博客中所有原创文章除特别声明外,均允许规范转载,转载请注明出处。所有非原创文章,按照原作者要求转载。


By Yurchiu.
其他物件杂物收纳
Hitokoto

Yurchiu 说,除了她以外的人都很强!嘤嘤嘤~~
博客信息
文章数目
158
最近更新
08-21
本站字数
350.6k
文章目录