Kalıp #24
Knapsack ve Alt Küme DP
İleriKapasite altında öğe seç veya tam toplam/hedefe vur.
Ne zaman kullanılır
Ağırlık/değerli öğelerde 0/1 seçimler, eşit alt küme bölümü, +/- ile hedef toplam.
Tanıma ipuçları
- Eşit alt küme toplamı bölümü
- Hedef toplam / coin change II
- Boolean erişilebilir dp[cap]
Yaygın tuzaklar
- 0/1 vs sınırsız döngü sırası (geriye vs ileri)
- Toplam tek olduğunda yarım-toplam taşması
- 1D ters yineleme yeterken 2D kullanmak
90 saniyelik tanıma egzersizi
Hangisi en iyi uyuyor?
- Eşit alt küme toplamı bölümü
- Hedef toplam / coin change II
- Boolean erişilebilir dp[cap]
Interactive
Zihinsel model
Değişmezin tam adım adım anlatımı. Duraklat, noktalara tıkla veya ← → kullan. Her adımı kendi cümlelerinle anlatmayı hedefle.
Adım 1 / 8
0
1
2
3
4
5
dp[c] = best value
0/1 knapsack, capacity 5, items (2,3) and (3,4).
Nasıl düşünülür
dp[c] = kapasite c ile en iyi değer (veya erişilebilir bool). 0/1 için kapasiteyi aşağı tara ki her öğe bir kez kullanılsın. Sınırsız için yukarı tara. Alt küme-toplamı value=weight ve bool OR knapsack’tır.
Şablon şekilleri
| Şekil | Temel hamle | Notlar |
|---|---|---|
| 0/1 knapsack | c = W..w | dp[c]=max(dp[c], dp[c-w]+v) |
| Sınırsız | c = w..W | Coin, kombinasyon |
| Alt küme toplam | bool dp | Bölüm / hedef |
Karmaşıklık temeli
Klasik knapsack O(n·W) zaman ve O(W) alan.
Şablondan probleme
- 0/1 vs sınırsız ayırt et.
- Kapasite W koy (sıkça sum/2).
- dp[0]=0 veya true; öğe başına doldur.
- dp[W] veya yol sayısını oku.
Şablon
TypeScript, Python ve C#’te aynı iskelet. Değişmezi uyarla; yapıyı koru.
Knapsack ve Alt Küme DP · Şablon
/** Knapsack template: partition equal subset sum (0/1 bool DP). */
export function canPartition(nums: number[]): boolean {
const sum = nums.reduce((a, b) => a + b, 0);
if (sum % 2) return false;
const target = sum / 2;
const dp = new Array<boolean>(target + 1).fill(false);
dp[0] = true;
for (const x of nums) {
for (let c = target; c >= x; c--) dp[c] = dp[c]! || dp[c - x]!;
}
return dp[target]!;
}
/** Knapsack template: partition equal subset sum (0/1 bool DP). */
export function canPartition(nums: number[]): boolean {
const sum = nums.reduce((a, b) => a + b, 0);
if (sum % 2) return false;
const target = sum / 2;
const dp = new Array<boolean>(target + 1).fill(false);
dp[0] = true;
for (const x of nums) {
for (let c = target; c >= x; c--) dp[c] = dp[c]! || dp[c - x]!;
}
return dp[target]!;
}
#DurumProblemTürZorlukBitti
- 1#416 Partition Equal Subset SumRehbermedium
- 2#474 Ones and ZeroesRehbermedium
- 3#494 Target SumRehbermedium
- 4#518 Coin Change IIRehbermedium
- 5#879 Profitable SchemesRehberhard
- 6#1049 Last Stone Weight IIRehbermedium