বিটমাস্ক ডিপি (Bitmask DP)
ধরুন আপনার কাছে n টি সুইচ সহ একটি লাইট সুইচের প্যানেল আছে। প্রতিটি সুইচ হতে পারে অন (ON) অথবা অফ (OFF)। যেকোনো মুহূর্তে সমস্ত সুইচের অবস্থা — যেমন ধরুন ৩, ও ৪ নম্বর সুইচ দুটো অন — এই অন থাকা সুইচগুলো আপনি যে আইটেমগুলো বেছে নিয়েছেন মূলত তাদের একটি সাবসেট (subset) নির্দেশ করে।
এখন এখানে চতুর একটি কৌশল বা ট্রিক রয়েছে: আপনি কোন কোন সুইচগুলো অন রেখেছেন তার একটি তালিকা তৈরি না করে, আপনি বরং সরাসরি একটি বাইনারি সংখ্যাই লিখতে পারেন। সুইচ 0 অন = বিট 0 এর মান 1। সুইচ 3 অন = বিট 3 এর মান 1। যদি সব সুইচ অফ থাকে = তাহলে আপনার সংখ্যাটি হলো 0। আর সব সুইচ অন থাকলে = সংখ্যাটি হবে \(2^n\) − 1।
এই নির্দিষ্ট ইনটিজারটিকে বা পূর্ণসংখ্যাটিকে বিটমাস্ক (bitmask) বলা হয়, এবং সমস্ত সম্ভাব্য বিটমাস্কগুলোর ওপর ডাইনামিক প্রোগ্রামিং (DP বা dynamic programming) ব্যবহার করাকেই বিটমাস্ক ডিপি (Bitmask DP) বলা হয়।
এটি কীভাবে কাজে আসে?
কিছু সমস্যা এমন হতে পারে: "প্রতিটি আইটেম ঠিক একবার করেই ভিজিট করে, আইটেমগুলোতে নির্দিষ্ট স্লট বরাদ্দ করার সবচেয়ে সেরা উপায় বা পদ্ধতি কোনটি?" ব্রুট-ফোর্স (Brute force) পদ্ধতিতে এর প্রতিটি সম্ভাব্য ক্রমানুসারে বা অর্ডারে চেষ্টা করা হয় — যা হলো সব মিলিয়ে n! টি সম্ভাবনা, আর n এর মান 13 এর মতো ছোট হলেও এটি সব মিলিয়ে বিশাল বা বিস্ফোরিত একটি অবস্থা তৈরি করে। বিটমাস্ক ডিপি (Bitmask DP) প্রতিটি নির্দিষ্ট অবস্থান বা অর্ডারের পরিবর্তে কোন আইটেম বা জিনিসগুলো ইতোমধ্যে ব্যবহার করা হয়েছে তা ট্র্যাক করে, যা পুরো কাজটিকে n! অবস্থা থেকে প্রায় \(2^n\) × n এ নামিয়ে আনে — যা যদিও অনেক অনেক বড় বা সূচকীয় (exponential), কিন্তু n ≈ 20 হওয়া পর্যন্ত এটি বেশ সহজেই ব্যবহার এবং ম্যানেজ করা যায়।
মূল স্টেট বা কোর স্টেট (The Core State)
এর ডিপি (DP) স্টেটটি হলো dp[mask][i], এর অর্থ হলো: "আমি ইতিমধ্যে mask এ থাকা শহরগুলোতে (বা আইটেমগুলোতে) ঘুরে এসেছি, এবং আমি বর্তমানে i তম শহরে রয়েছি।" আপনার এর জন্য যে বিট ট্রিকস (bit tricks) গুলো প্রয়োজন তা হলো:
- j তম শহরটি মাস্কে (mask) আছে কি না তা যাচাই করুন:
(mask >> j) & 1 - j তম শহরটিকে মাস্কে (mask) যোগ করুন:
mask | (1 << j) - j তম শহরটিকে মাস্ক (mask) থেকে সরিয়ে ফেলুন:
mask & ~(1 << j) - মাস্কটি কি সম্পূর্ণরূপে ভিজিট করা হয়েছে?
mask == (1 << n) - 1
ট্র্যাভেলিং সেলসপারসন সমস্যা (Travelling Salesperson Problem - TSP)
সবচেয়ে বিখ্যাত এবং বহুল ব্যবহৃত বিটমাস্ক ডিপি (Bitmask DP) প্রয়োগ: কিছু n সংখ্যক শহর এবং তাদের প্রত্যেক জোড়ার মধ্যে ভ্রমণের খরচ দেওয়া থাকে, তখন সবচেয়ে সস্তা বা কম খরচে প্রতিটি শহরে ঠিক একবার করে ভ্রমণ করে আবার বাড়ি ফিরে আসার উপায়টি খুঁজে বের করতে হয়।
বেস কেস বা শর্ত: dp[1][0] = 0 — অর্থাৎ আমরা 0 নম্বর শহর থেকে শুরু করি, যেখানে শুধুমাত্র 0 নম্বর শহরটিই ভিজিট বা পরিদর্শন করা হয়েছে (0 তম বিটের মান 1), আর এতে কোনো খরচ বা কস্ট হয়নি।
ট্রানজিশন (Transition): প্রতিটি ভিজিট না করা (unvisited) বা বাকি থাকা শহর j এর জন্য, বর্তমান রুটটিকে বা ট্যুরটিকে আরেকটু বড় করার চেষ্টা করুন: dp[mask | (1<<j)][j] = min(dp[mask][i] + cost[i][j])।
উত্তর বা ফলাফল (Answer): সব শহর ঘুরে আবার বাড়ি ফিরে আসার সবচেয়ে সস্তা বা কম খরচের পথটি হলো: min over all i of (dp[full_mask][i] + cost[i][0])।
বিটমাস্ক ডিপি দিয়ে ট্র্যাভেলিং সেলসপারসন সমস্যা বা TSP (TSP with Bitmask DP)
অ্যাসাইনমেন্ট সমস্যা (Assignment Problem)
মোট খরচ বা কস্টগুলোকে যতটা সম্ভব কমিয়ে n জন কর্মীকে n টি কাজে নিযুক্ত বা অ্যাসাইন করুন। এর স্টেট (state) অপেক্ষাকৃত সহজ: dp[mask] = mask এর কাজগুলো সম্পন্ন করতে সর্বনিম্ন খরচ, যেখানে আমরা ক্রমানুসারে একটির পর একটি কাজ কোনো নির্দিষ্ট কর্মীকে দিয়ে থাকি।
যদি mask এ মোট k টি বিট সেট করা থাকে, তবে আমরা k তম কর্মীকে (0-indexed) নিযুক্ত করছি। mask এ আগে থেকেই থাকা প্রতিটি কাজ j এর ক্ষেত্রে, আমরা হয়তো তাকে সর্বশেষ নিযুক্ত করতে পারতাম: dp[mask] = min(dp[mask ^ (1<<j)] + cost[k-1][j])।
সাবসেটের ওপর ইটারেট করা বা লুপ চালানো (Iterating Over Subsets)
এটি একটি অসাধারণ এবং অত্যন্ত শক্তিশালী প্যাটার্ন: একটি নির্দিষ্ট বা প্রদত্ত মাস্কের (mask) সমস্ত সাবসেটের ওপর ইটারেট (iterate) করা বা ঘুরে আসা। for (sub = mask; sub > 0; sub = (sub-1) & mask) এই লুপটি mask এর প্রতিটি নন-এমপ্টি (non-empty) সাবসেটের মধ্যে ঠিক একবারই ঘুরে আসে। এর কৌশলটি হলো: (sub-1) & mask অপারেশনটি mask এর ভেতরে সবচেয়ে ছোট বা পজিশনে নিচে থাকা সেট বিটটিকে ক্লিয়ার করে বা সরিয়ে দিয়ে, ঠিক \(O(2^{\text{popcount}(mask)})\) সময়ে সমস্ত সাবসেটের মধ্য দিয়ে এগিয়ে যায়। সমস্ত মাস্কগুলোকে একত্রিত করলে সব মিলিয়ে \(3^n\) টি ধাপ বা স্টেপ তৈরি হয়।
Complexity
ছোট কুইজ
পড়া চালিয়ে যান