码迷,mamicode.com
首页 > 其他好文 > 详细

Guarding the Chessboard(UVa 11214)

时间:2017-09-13 23:17:28      阅读:267      评论:0      收藏:0      [点我收藏+]

标签:搜索   开始   cst   size   ida   break   ems   mem   算法   

本题题意:

输入一个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)

标签:搜索   开始   cst   size   ida   break   ems   mem   算法   

原文地址:http://www.cnblogs.com/sapphirebitter/p/7518043.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!