バックパックに関する9つの講義(2)-完全なバックパックの問題

バックパックに関する9つの講義(2)-完全なバックパックの問題

ここからダウンロードできる有名なバックパッキングに関する9つのレクチャー前の記事の01バックパックの問題を参照してください。

1.1問題

バックパックにNさまざまな種類の商品と容量がありV、各アイテムには無制限のメンバーがあり、最初のiコストのアイテムにはC iC_iがありますC、得られる値はW iW_iです。W全体的な価値を最大化するためにバックパックにパックするアイテムを見つけます。

1.2問題解決のアイデア

完全なバックパックと01バックパックの唯一の違いは、アイテムを複数回選択できるかどうかです。

この違いを知っていると、実際、慎重に考えると、単一のアイテムC i C_iについて、容量Vが制限されているため、バックパックの問題を01バックパックに完全に変換できます。C言い換えれば、⌊V/Ci⌋\ left \ lfloor V / C_i \ right \ rfloorのようにしか置くことができませんV / C個なので、完全なバックパックの問題を⌊V/C1⌋\ left \ lfloor V / C_1 \ right \ rfloorと見なすだけで済みます。V / C1アイテムC1 C_1C1、有⌊V/C2⌋\ left \ lfloor V / C_2 \ right \ rfloorV / C2アイテムC2 C_2C2、…、⌊V/CN⌋\ left \ lfloor V / C_N \ right \ rfloorV / CNアイテムCN C_NCN01バックパックの問題で十分です。ただし、この時点での全体的な複雑さは、O(NV ∑ VC i)O(NV \ sum \ cfrac {V} {C_i})と見なすことができますO N VCV、この複雑さは少し高いです〜

さらに、実際にはより効率的な変換方法があります。バイナリ思考を使用して、i番目のアイテムをC i 2 K C_i2 ^ Kのコストに分解できます。C2K、値はW i 2 k W_i2 ^ kです。W2k個のアイテム。ここでkは1からCi2k≤VC_i2^C2kVの最大整数(実際、kはすべてのiアイテムのコストを取り、V未満の整数を取ることができます)、次に時間の複雑さをO(NV log(⌊V/C2⌋))O(NVlog(\ left \ lfloor V / C_2 \ right \ rfloor))O N VのL O G V / C2もう一度。以前よりずっと低い〜

もちろん、ほとんどのnbソリューションは上記のhhhではありません。01ナップザックの問題を解決するには、vvが必要です。v V、V − 1、..、0 V、V-1、..、0から降順V V1 0 dp [v] dp [v]を計算しますd p [ v ] vのデクリメント計算は、状態dp [v] dp [v]を保証することですd p [ v ]前のラウンドから再帰的に導出されます。実際には、アイテムが1回だけ選択されるようにするためですが、現在は複数回選択できます。それは美しいではありませんか?非常に簡単です。vをインクリメントしてdp [vを計算します。 ]はい、次の疑似コードを参照してください。

dp[0...V]0
for i ← 1 to N  // 依次遍历N件物品
	for v ← Ci to V // 能装下当前物品的背包使用状态方程
		dp[v] ← max{
    
    dp[v], dp[v-Ci]+Wi}

したがって、現時点では、問題の複雑さはO(NV)O(NV)に減少しています。O N V 、秒〜

しかし、01バックパックの絶え間ない最適化は完全なバックパックには存在しません〜

2つの項目i、jがC i <C j C_i \ lt C_jを満たす場合、単純で効果的な最適化C<CJ連結Wi≥WjW_i\ ge W_jWWJ、次に、アイテムjを直接削除できます。このプロセスは、O(N 2)O(N ^ 2)で行うことができます。O N2時間の複雑さはそれほど高くありません。時間に追われている場合は、この単純な最適化を試すことができます〜

1.3サンプルコード

私は書くのが面倒です〜01バックパック問題コードと同様に、独自のデータを作成する必要があります

1.4実際の戦闘段階

いくつか質問をしてください、そしてそれは明らかになるでしょう!

LuoguP1616クレイジーメディシンコレクション

タイトルの説明

Li Yuxiangは才能のある子供であり、彼の夢は世界で最も偉大な医師になることです。このため、彼は近くで最も権威のある医師を教師として崇拝したかったのです。彼の適性を判断するために、医者は彼に難しい問題を提示した。医者は彼をハーブでいっぱいの洞窟に連れて行き、彼に言った:「私の子供、この洞窟にはいくつかの異なる種類のハーブがあります。それぞれを選ぶのに時間がかかり、それぞれに独自の価値があります。私はいくつかのハーブを集めることができる期間を与えてください。あなたが賢い子供であるならば、あなたはあなたが集めるハーブの総価値を最大にすることができるはずです。」

LiYuxiangの場合、このタスクを完了できますか?

この質問と元の質問の違い:

  1. 各ハーブは制限なしに乱暴選ぶことができます

  2. 薬の種類が眩しくて、薬を集める時間がとても長いです!マスターは菊が感謝するのを待っていました!

特定の入力および出力形式とサンプルについては、元の質問のWebサイトを参照してください〜


これは典型的な完全なナップザックの問題です。上記のアイデアに従って直接書き込むことができますが、この質問のデータ量は比較的多いです。dp配列のlong longタイプに注意し、メモリの爆発を防ぐために配列を動的に生成します。STLもあります。mallocをゆっくり使う

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main() {
    
    
	ios::sync_with_stdio(false), cin.tie(NULL);
	// 静态数组会爆内存
	//int V[N] = { 0 }, C[N] = { 0 }, t, m;
	//long long dp[N] = { 0 };

	int t, m;
	cin >> t >> m;
	int* V = (int*)malloc(m * sizeof(int));
	int* C = (int*)malloc(m * sizeof(int));
	long long* dp = (long long*)malloc((t+1) * sizeof(long long));
	// STL太慢了
	//vector<int> V(m);
	//vector<int> C(m);
	//vector<long long> dp(t+1);
	for (int i = 0; i < m; i++) {
    
    
		cin >> C[i] >> V[i];
	}
	for (int i = 0; i < m; i++) {
    
    
		for (int j = C[i]; j <= t; j++) {
    
    
			dp[j] = max(dp[j], dp[j - C[i]] + V[i]);
		}
	}
	cout << dp[t] << endl;
	free(V);
	free(C);
	free(dp);
	return 0;
}

結果の送信:

07Kye1.png

STLを使用する場合。

07KWWD.png

STLはmallocの2倍です〜もちろん、ここで時間が止まらなければ効果はありません

おすすめ

転載: blog.csdn.net/weixin_44338712/article/details/109105987