برنامه نویسی
رونمایی از پشت پرده: تسلط بر تکنیک های جستجوی و هرس اول

Backtracking یک روش سیستماتیک برای تکرار از طریق تمام تنظیمات احتمالی یک مشکل است. اغلب برای حل مشکلات در جایی که باید دنباله ای از تصمیمات اتخاذ شود ، استفاده می شود و هر تصمیم به مجموعه جدیدی از امکانات منتهی می شود. استفاده از پشتی استفاده می کند عمق اول جستجو (DFS) برای کشف فضای دولت ، و آن را استخدام می کند توابع هرس برای از بین بردن مسیرهای نامعتبر یا زیر حد متوسط در مراحل جستجو.
مؤلفه های مشکلات برگشت
- حالت اولیه: نقطه شروع مشکل.
- حالت هدف/هدف: راه حل مورد نظر.
- حالتهای متوسط: کشورهایی که هنگام حرکت از حالت اولیه به حالت هدف تولید می شوند.
- مسیر: دنباله حالتها از حالت اولیه به حالت هدف.
- عملگر: قوانین یا اقداماتی که یک حالت را به دیگری تبدیل می کنند.
- تابع هرس: یک اکتشافی برای از بین بردن حالت های نامعتبر یا زیر حد اولیه.
الگوریتم پشت پرده
- با حالت اولیه شروع کنید.
- برای کشف تمام حالتهای ممکن از DFS استفاده کنید.
- اگر یک حالت نامعتبر است (بر اساس عملکرد هرس) ، عقب بکشید و مسیر دیگری را امتحان کنید.
- اگر یک کشور وضعیت هدف است ، راه حل را برگردانید.
- تکرار کنید تا تمام حالتهای ممکن مورد بررسی قرار گیرد یا راه حل پیدا شود.
مشکلات مثال با استفاده از backtracking حل شده است
1 مشکل قفل 3 رقمی
- حالت اولیه: “111”
- حالت هدف: ترکیب صحیح (به عنوان مثال ، “352”)
- عملگر: افزایش هر رقم توسط 1 (از 1 تا 9).
- تابع هرس: اگر یک رقم صحیح است (به عنوان مثال ، “کلیک”) ، آن را برطرف کرده و به رقم بعدی حرکت کنید.
اجرای:
function findLockCombination(target) {
function backtrack(combination, index) {
if (combination === target) {
console.log("Found combination:", combination);
return true;
}
if (index >= 3) return false;
for (let i = 1; i <= 9; i++) {
const newCombination = combination.slice(0, index) + i + combination.slice(index + 1);
if (newCombination[index] === target[index]) {
console.log("Click at position", index + 1, "with digit", i);
if (backtrack(newCombination, index + 1)) return true;
}
}
return false;
}
backtrack("111", 0);
}
const targetCombination = "352";
findLockCombination(targetCombination);
2 مشکل راهبان و شیاطین
- حالت اولیه: 3 راهب ، 3 شیاطین و قایق در ساحل سمت چپ.
- حالت هدف: همه راهبان و شیاطین در ساحل راست.
- عملگر: 1 یا 2 نفر را در قایق حرکت دهید.
- تابع هرس: اطمینان حاصل کنید که راهبان هرگز توسط شیاطین در هر یک از ساحل ها بیشتر نیستند.
اجرای:
function solveMonksAndDemons() {
const initialState = { left: { monks: 3, demons: 3 }, right: { monks: 0, demons: 0 }, boat: "left" };
const visited = new Set();
function isSafe(state) {
const { left, right } = state;
return (
(left.monks === 0 || left.monks >= left.demons) &&
(right.monks === 0 || right.monks >= right.demons)
);
}
function backtrack(state, path = []) {
const key = JSON.stringify(state);
if (visited.has(key)) return false;
visited.add(key);
if (state.left.monks === 0 && state.left.demons === 0) {
console.log("Solution found:", path);
return true;
}
const { left, right, boat } = state;
const moves = [
{ monks: 1, demons: 0 },
{ monks: 2, demons: 0 },
{ monks: 0, demons: 1 },
{ monks: 0, demons: 2 },
{ monks: 1, demons: 1 },
];
for (const move of moves) {
if (
(boat === "left" && left.monks >= move.monks && left.demons >= move.demons) ||
(boat === "right" && right.monks >= move.monks && right.demons >= move.demons)
) {
const newLeft = {
monks: left.monks - (boat === "left" ? move.monks : -move.monks),
demons: left.demons - (boat === "left" ? move.demons : -move.demons),
};
const newRight = {
monks: right.monks - (boat === "right" ? move.monks : -move.monks),
demons: right.demons - (boat === "right" ? move.demons : -move.demons),
};
const newState = {
left: newLeft,
right: newRight,
boat: boat === "left" ? "right" : "left",
};
if (isSafe(newState) && backtrack(newState, [...path, newState])) {
return true;
}
}
}
return false;
}
backtrack(initialState);
}
solveMonksAndDemons();
3 مشکل کشاورز ، بز ، کلم و گرگ
- حالت اولیه: کشاورز ، بز ، کلم و گرگ در ساحل سمت چپ.
- حالت هدف: همه در ساحل راست.
- عملگر: کشاورز می تواند یک مورد (بز ، کلم یا گرگ) را در قایق ببرد.
- تابع هرس: اطمینان حاصل کنید که بز تنها با کلم باقی نماند و گرگ با بز تنها باقی نمی ماند.
اجرای:
function solveFarmerProblem() {
const initialState = {
left: ["farmer", "goat", "cabbage", "wolf"],
right: [],
boat: "left",
};
const visited = new Set();
function isSafe(state) {
const unsafe = (side) =>
(side.includes("goat") &&
side.includes("cabbage") &&
!side.includes("farmer")) ||
(side.includes("wolf") &&
side.includes("goat") &&
!side.includes("farmer"));
return !(unsafe(state.left) || unsafe(state.right));
}
function stateKey(state) {
return JSON.stringify(state);
}
function backtrack(state, path = []) {
if (state.left.length === 0) {
console.log("Solution found:", path);
return true;
}
const key = stateKey(state);
if (visited.has(key)) return false;
visited.add(key);
const { left, right, boat } = state;
const fromShore = boat === "left" ? left : right;
// Possible moves: Farmer alone or Farmer + one item
for (const item of [...fromShore, null]) {
if (item === null || item !== "farmer") {
let newLeft = [...left];
let newRight = [...right];
if (boat === "left") {
newLeft = newLeft.filter((x) => x !== "farmer" && x !== item);
newRight = [...newRight, "farmer"];
if (item) newRight.push(item);
} else {
newRight = newRight.filter((x) => x !== "farmer" && x !== item);
newLeft = [...newLeft, "farmer"];
if (item) newLeft.push(item);
}
const newState = {
left: newLeft,
right: newRight,
boat: boat === "left" ? "right" : "left",
};
if (isSafe(newState) && backtrack(newState, [...path, newState])) {
return true;
}
}
}
return false;
}
backtrack(initialState);
}
solveFarmerProblem();
4 مشکل کوزه آب
- حالت اولیه: هر دو کوزه خالی هستند.
- حالت هدف: 2 گالن در کوزه 4 گالن.
- عملگر: پر ، خالی یا آب را بین کوزه ها پر کنید.
- تابع هرس: از تجدید نظر در ایالات جلوگیری کنید.
اجرای:
function solveWaterJug() {
const initialState = { jug4: 0, jug3: 0 };
const target = 2;
const visited = new Set();
function backtrack(state, path = []) {
const key = `${state.jug4},${state.jug3}`;
if (visited.has(key)) return false;
visited.add(key);
if (state.jug4 === target) {
console.log("Solution found:", path);
return true;
}
const { jug4, jug3 } = state;
const moves = [
{ jug4: 4, jug3 }, // Fill jug4
{ jug4, jug3: 3 }, // Fill jug3
{ jug4: 0, jug3 }, // Empty jug4
{ jug4, jug3: 0 }, // Empty jug3
{ jug4: Math.max(0, jug4 - (3 - jug3)), jug3: Math.min(3, jug3 + jug4) }, // Pour jug4 to jug3
{ jug4: Math.min(4, jug4 + jug3), jug3: Math.max(0, jug3 - (4 - jug4)) }, // Pour jug3 to jug4
];
for (const move of moves) {
if (backtrack(move, [...path, move])) {
return true;
}
}
return false;
}
backtrack(initialState);
}
solveWaterJug();
نکات کلیدی:
- بازگشت به عقب روش نظامتی برای کشف همه راه حل های ممکن.
- استفاده می کند عمق اول جستجو وت توابع هرس برای از بین بردن مسیرهای نامعتبر.
- برای حل مفید است مشکلات NP-HARD مانند معماها ، مشکلات رضایت محدودیت و بهینه سازی ترکیبی.