UVa 11214 Guarding the Chessboard 守卫棋盘 ID 迭代加深搜

该文章介绍了一种使用迭代加深搜索(IDDFS)解决棋盘上防止最少数量的皇后覆盖或攻击特定点的方法。通过四个数组记录行、列和对角线的覆盖状态,利用DFS策略尝试放置皇后,并检查所有点是否被覆盖。当找到解决方案时,输出最少的皇后数量。
摘要由CSDN通过智能技术生成

题目链接:UVa 11214
题目描述:

给定一个 n × m n\times m n×m的棋盘,棋盘中的某些点是被标记的,你需要防止最少的皇后,让皇后覆盖这些点或者攻击这些点,输出最少的皇后数量。
注意:一个皇后的攻击范围为其所在行和列以及两条对角线。

题解:

本题我们可以使用迭代加深搜来求解,我们只需要依次枚举放置皇后的数量,然后使用 D F S DFS DFS放置皇后,到最终时候判断棋盘中的点时候全部被覆盖即可。我们需要用四个数组来表示覆盖情况,这四个数组分别表示:某一行是否被覆盖,某一列是否被覆盖,某条主对角线是否被覆盖,某条副对角线是否被覆盖。容易发现的是:同一条主对角线上的点的横纵坐标之差相等,而同一条副对角线上的横纵坐标之和相等,所以我们就可以通过横纵坐标的和与差来判断改点属于的对角线。

代码:

#include <bits/stdc++.h>

const int MAXN = 10;

using namespace std;

int caseID, maxDepth, n, m;
string board[MAXN];
bool vis[4][MAXN * 2];

bool cover()
{
    for (int i = 0; i < n; i++) {
        if (vis[0][i]) { continue; }
        for (int j = 0; j < m; j++) {
            if (board[i][j] != 'X') { continue; }
            if (vis[1][j] || vis[2][i + j] || vis[3][i - j + MAXN]) { continue; }
            return false;
        }
    }
    return true;
}

bool dfs(int nowDepth, int nowRow)
{
    if (nowDepth == maxDepth) {
        return cover();
    }
    if (n - nowRow < maxDepth - nowDepth) { return false; }
    int temp[4] = {0};
    for (int j = 0; j < m; j++) { // 选择放置位置
        temp[0] = vis[0][nowRow];
        temp[1] = vis[1][j];
        temp[2] = vis[2][nowRow + j];
        temp[3] = vis[3][nowRow - j + MAXN];
        vis[0][nowRow] = true;
        vis[1][j] = true;
        vis[2][nowRow + j] = true;
        vis[3][nowRow - j + MAXN] = true;
        if (dfs(nowDepth + 1, nowRow + 1)) { return true; };
        vis[0][nowRow] = temp[0];
        vis[1][j] = temp[1];
        vis[2][nowRow + j] = temp[2];
        vis[3][nowRow - j + MAXN] = temp[3];

    }
    if (dfs(nowDepth, nowRow + 1)) { return true; } // 当前这一行不放
    return false;

}

bool getInput()
{
    cin >> n;
    if (n == 0) { return false; }
    cin >> m;
    for (int i = 0; i < n; i++) {
        cin >> board[i];
    }
    return true;
}

int main()
{
    while (getInput()) {
        memset(vis, 0, sizeof(vis));
        for (maxDepth = 0; ; maxDepth++) {
            if (dfs(0, 0)) {
                caseID++;
                cout << "Case " << caseID << ": " << maxDepth << endl;
                break;
            }
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值