回溯初级

回溯算法

一种带有条件限制的穷举算法

1. 常用场景

在某种限制下求可行方案数最优解

2. 算法思想

在满足条件的情况下选择一个方法/路径进行运算,运算完毕后回到选择之前,换一种选择继续运算,直至无选择。

3. 模板

回溯算法往往和递归密切相关,一般模板如下:

void dfs() {
	if (terminating condition)
	for (alternative) {
		dfs();
		recover
	}
}

4. 经典例题

  • N皇后
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 8;
int dx[] = {-1, -1, -1, 0, 0, 1, 1, 1};
int dy[] = {-1, 0, 1, -1, 1, -1, 0, 1};
int ans = 0;

vector<vector<int>> board(N, vector<int>(N, 0));

void use(int x, int y) {
    int xx, yy;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < 8; j++) {
            xx = x + i * dx[j];
            yy = y + i * dy[j];
            if (xx >= 0 && xx < N && yy >= 0 && yy < N) {
                board[xx][yy] = 1;
            }
        }
    }
}
void dfs(int x, int t) {
    if (t == N) {
        ans++;
        return;
    }
    vector<vector<int>> tmp = board;
    for (int i = 0; i < N; i++) {
        if (!board[x][i]) {
            use(x, i);
            dfs(x + 1, t + 1);
        }
        board = tmp;
    }
}
int main() {
    dfs(0, 0);
    cout << ans << endl;
    return 0;
}
  • POJ1321 棋盘问题
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

const int N = 10;
int n, k, ans;
int vis[10];
char board[N][N];

void dfs(int x, int t) {
    if (t == k) {
        ans++;
        return;
    }
    if (x == n)
        return;
    for (int i = 0; i < n; i++) {
        if (vis[i] || board[x][i] != '#')
            continue;
        vis[i] = 1;
        dfs(x + 1, t + 1);
        vis[i] = 0;
    }
    dfs(x + 1, t);
}

int main() {
    while (scanf("%d %d",&n,&k)) {
        if (n == -1 && k == -1)
            break;
        for (int i = 0; i < n; i++)
            scanf("%s", board[i]);
        ans = 0;
        dfs(0, 0);
        printf("%d\n", ans);
    }
    return 0;
}
posted @ 2021-06-04 02:26  Ybitsec  阅读(41)  评论(0编辑  收藏  举报