เรามี Binary String (สตริงที่ประกอบด้วย ‘1’ และ ‘0’ เท่านั้น) ความยาว ซึ่งหากเราพิจารณา String ความยาว ทุกรูปแบบ จะพบว่ามี รูปแบบ โดยแต่ละรูปแบบ จะมีค่าน้ำหนัก
การลดทอนคุณภาพ จะเป็นการเปลี่ยน ‘1’ เป็น ‘0’ ซึ่งสามารถทำได้ 2 วิธี
โดยเมื่อได้ Binary String ใหม่ที่เกิดจากการเปลี่ยน ‘1’ เป็น ‘0’ เราจะบวกค่าน้ำหนักของ Binary String ในขณะนั้น ไปกับ "ค่าลดทอนคุณภาพ"
แล้ว Operation นี้ จะจบลงเมื่อ String กลายเป็น “00000…0” ซึ่งเราจะต้องการให้ ค่าลดทอนคุณภาพ ค่ามากที่สุด
Binary String ที่กำหนดให้:
ขั้นตอน:
ค่าลดทอนคุณภาพ เริ่มต้นที่ = 3
ดังนั้น คำตอบของ Binary String คือ 13
โดยโจทย์จะกำหนด Binary String มาให้ อัน และให้ตอบให้ครบ
เขียนโค้ดเพื่อหา ค่าลดทอนคุณภาพ ที่มีค่ามากที่สุด สำหรับ Binary String ทั้ง อัน
สำหรับข้อนี้ เราจะใช้สิ่งที่เรียกว่า Bitmask DP ซึ่งเป็นรูปแบบการทำ Dynamic Programming ที่จะค่อนข้างพิสดารเล็กน้อย
โดย Bitmask DP นั้น ลักษณะจะเป็นการเล่นกับ เลขฐานสอง ซึ่งแทนที่จะเก็บ DP ในแต่ละ Index เราจะเก็บ DP ในแต่ละ Mask (เลขฐานสอง) แทน นั่นคือ เราจะมีทั้งหมด Mask (เราต้องการเล่นกับทุกรูปแบบของเลขฐานสองที่มี หลัก)
โดยโจทย์ส่วนใหญ่นั้น เราจะเก็บ State DP ในลักษณะของ
ลักษณะการทำ Bitmask DP ทั่วไปคือ

โดยในโจทย์ข้อนี้ เราจะกำหนดลักษณะ DP เป็นรูปแบบที่ 2 นั่นคือ ค่าที่ต่ำที่สุดที่จะนำเรามายัง state ที่
ก่อนอื่น เราก็จะต้องรับ input ว่า สำหรับแต่ละ ค่าลดทอนคุณภาพของมันจะเป็นเท่าไหร่ เราก็จะรับ input มาเป็น Binary String แล้วก็เข้า function ที่เขียนไว้ เพื่อแปลง Binary String เป็น เลขฐานสิบ
หลักจากนั้น เราก็แค่นำไอเดียของ Bitmask DP ด้านบน ลงมาใช้ โดยเราจะเก็บว่า คำตอบที่มากที่สุดสำหรับ เป็นเท่าไหร่ โดยเราจะ Loop ไปทุกๆ (นั่นคือ วน รอบ) โดยสำหรับแต่ละ จะคำนวณดังนี้:
แล้วเมื่อรับคำถามมา เราก็แค่ส่ง Output ไปเป็น สำหรับแต่ละอินพุตได้เลย
#include <bits/stdc++.h>
using namespace std;
const long long mod = 1e9 + 7;
const long long inf = 1e18;
long long binary(string s){
long long ans = 0;
reverse(all(s));
for (long long i = 0; i < s.length(); i++) {
ans += (s[i] - '0') * (1 << i);
}
return ans;
}
int32_t main(){
cin.tie(NULL)->sync_with_stdio(false);
long long n, q; cin >> n >> q;
vector <long long> a(1 << n);
for (long long i = 0; i < (1 << n); i++) {
string s; cin >> s;
long long num; cin >> num;
a[binary(s)] = num;
}
vector <long long> dp(1 << n, -inf); dp[0] = 0;
for (long long mask = 1; mask < (1 << n); mask++) {
// swap 1 bit
for (long long i = 0; i < n; i++) {
if ((mask & (1 << i)) == 0) continue;
long long nm = mask ^ (1 << i);
dp[mask] = max(dp[mask], dp[nm] + a[mask]);
}
// swap 2 bits
for (long long i = 0; i < n - 1; i++) {
if ((mask & (1 << i)) == 0 || (mask & (1 << (i + 1))) == 0) continue;
long long nm = mask ^ (1 << i) ^ (1 << (i + 1));
dp[mask] = max(dp[mask], dp[nm] + a[mask]);
}
}
while (q--) {
string s; cin >> s;
cout << dp[binary(s)] << "\n";
}
}
หากมีข้อสงสัย comment ไว้ใต้ post ได้เลยนะครับ 🙇♂️🙇♂️
ศึกษาโจทย์เพิ่มเติมได้ที่ Fast X Fourier