1. 程式人生 > >動態規劃之01揹包,完全揹包,分組揹包

動態規劃之01揹包,完全揹包,分組揹包

一:01揹包

每樣物品只能取一件

狀態轉移方程 f[i][v]=max(f[i-1][v],f[i-1][v-weight[i]]+cost[i])

f[i][v]表示前i件物品裝入v的空間裡的最大價值,考慮第i件物品是否放入的問題,一種是不放入那就是前i-1件物品放入v中,另一種考慮放入則是前i-1件物品放入v-weight[i]空間的最大值

將空間縮減成VN

for (int i = 0; i != n; ++i)
{
	for (int v = V; v >= things[i].weight; --v)
	{
		f[x] = max(f[x], f[x - things[i].weight] + things[i].price);
	}
}


二:完全揹包

由01揹包聯想,將每個物品能放的最大數量,按照二進位制的形式分成一個一個的小物品,例如5個1物品,能分成4個1物品和1個1物品,然後將4個1物品當成一個放入01揹包中,將1個1物品放入完全揹包中,時間複雜度為超O(VN)

若想時間複雜度不超,則模板

for (int i = 0; i != n; ++i)
{
	for (int v = things[i].weight; v <= V; ++v)
	{
		f[x] = max(f[x], f[x - things[i].weight] + things[i].price);
	}
}


三:多重揹包

N種物品和一個容量為V的揹包。第

i種物品最多有n[i]件可用,每件費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可使這些物品的費用總和不超過揹包容量,且價值總和最大。

void 01bag(int a,int b)//a表示價格,b表示重量
{
	for (int v = V; v >= b; --b)
	{
		f[v] = max(f[v], f[v - b] + a);
	}
}

void completebag(int a, int b) //a表示價格,b表示重量
{
	for (int v = b; v <= V; ++v)
	{
		f[v] = max(f[v], f[v - b] + a);
	}
}


void multibag(int a, int b, int c)//多重揹包c表示數量
{
	if (b*c >= V)
	{
		completebag(a, b);
		return;
	}
	int k = 1;
	while (c>=k)
	{
		01bag(a*k, b*k);
		c = c - k;
		k *= 2;
	}
	01bag(c*a, b*a);
}