Guarding the Chessboard(UVa 11214)

Posted sapphirebitter

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Guarding the Chessboard(UVa 11214)相关的知识,希望对你有一定的参考价值。

本题题意:

输入一个n*m的棋盘,某些格子有标记,用最少的皇后占据或者攻击所以带标记的格子。皇后的攻击范围为同行同列和同对角线。

可以使用IDA*算法,即从样例可以发现只需要最多5个棋子就可以对棋盘上所有地方进行攻击,因而使用IDA*进行对应的剪枝即可。

#include<cstdio>
#include<cstring>
using namespace std;

int n,m,kase=0,maxd;
bool vis[4][30];///表示皇后已经攻击的范围,vis[0][]中存储的是行,vis[1][]中存储的是每列,vis[2][]中存储的是每个副对角线,vis[3][]是每个主对角线
char chess[15][15];

bool dfs(int pos,int r)
{
    if(pos==maxd){
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            if(chess[i][j]==X&&!vis[0][i]&&!vis[1][j]&&!vis[2][i+j]&&!vis[3][i-j+n])///如果达到最大深度,但是仍有X点不处于皇后的攻击范围内,则剪枝
                return false;
        }
        return true;
    }
    for(int i=r;i<=n;i++)///从当前行开始,因为前面的行已经搜索过
    for(int j=1;j<=m;j++){
        if(!vis[0][i]||!vis[1][j]||!vis[2][i+j]||!vis[3][i-j+n]){///若存在有未被攻击的地方,则进行放棋
            bool v1=vis[0][i],v2=vis[1][j],v3=vis[2][i+j],v4=vis[3][i-j+n];
            vis[0][i]=vis[1][j]=vis[2][i+j]=vis[3][i-j+n]=true;
            if(dfs(pos+1,r+1)) return true;///若要放置棋子数最小,则皇后必定会放于是X的位置
            vis[0][i]=v1,vis[1][j]=v2,vis[2][i+j]=v3,vis[3][i-j+n]=v4;///还原
        }
    }
    return false;
}

int main()
{
    while(~scanf("%d%d",&n,&m)&&n)
    {
        for(int i=1;i<=n;i++) scanf("%s",chess[i]+1);
        for(maxd=1;maxd<5;maxd++)
        {
            memset(vis,0,sizeof(vis));
            if(dfs(0,0)) break;
        }
        printf("Case %d: %d\n",++kase,maxd);
    }
    return 0;
}

 

以上是关于Guarding the Chessboard(UVa 11214)的主要内容,如果未能解决你的问题,请参考以下文章

UVa11214 Guarding the Chessboard (IDA*)

UVA - 11214 Guarding the Chessboard (可重复覆盖,DLX+IDA*)

BZOJ1619[Usaco2008 Nov]Guarding the Farm 保卫牧场

1619: [Usaco2008 Nov]Guarding the Farm 保卫牧场 搜索

洛谷 P2919 [USACO08NOV]守护农场Guarding the Farm

[BZOJ] 1619: [Usaco2008 Nov]Guarding the Farm 保卫牧场