hrbust 1283 又见皇后

探讨在含有障碍物的n×n国际象棋棋盘上,如何放置最多的皇后,使得它们无法互相攻击。通过递归搜索算法寻找最优解。

又见皇后
Time Limit: 3000 MSMemory Limit: 65536 K
Total Submit: 122(33 users)Total Accepted: 45(25 users)Rating: Special Judge: No
Description
国际象棋中,皇后能攻击同一横线、同一竖线、同一斜线(45度)的敌人。

众所周知,有一个非常著名的算法问题,是求在一个n×n的国际象棋棋盘中最多能摆放多少个皇后,使其不能相互攻击。

今天我们暂且不要让问题如此理想化。假设棋盘上有一些障碍物,皇后不能摆在障碍物上,同时也不能穿过障碍物攻击别人。在此条件之下,棋盘上最多又能放多少个皇后?

                            

图中黑色方块表示障碍物,圆点表示皇后

2是一种最优摆法;图4、图5属于违规摆法

Input
输入包含多组数据。

每组数据的第一行是一个整数n1n8),表示棋盘的边长。之后的n行将描述棋盘,其中’X’表示该单元格有障碍物,’.’则表示没有。

n=0表示输入结束。

Output
对于每组数据,请输出一个整数表示最多能在棋盘上放几个皇后,使它们相互不能攻击。
每个答案占一行。

Sample Input
4

.X..

...X

XXX.

..X.

2

XX

.X

3

.X.

X.X

.X.

0

Sample Output
4

1

2




数据给的小/。。

时间也多。。

直接暴力跑。。

因为有阻隔点所以一行可能存在不止一个点。



#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 10
int res;
int n;
int m;
char maps[N][N];
int vis[N][N];
int judge(int x,int y)
{
    for(int i=y-1; i>=0&&maps[x][i]=='.'; i--)
        if(vis[x][i]==1)
            return 0;
    for(int i=x-1; i>=0&&maps[i][y]=='.'; i--)
    {
        if(vis[i][y]==1)
            return 0;
    }
    for(int i=x-1,j=y-1; i>=0&&maps[i][j]=='.'&&j>=0; j--,i--)
    {
        if(vis[i][j]==1)
            return 0;
    }
    for(int i=x-1,j=y+1; i>=0&&maps[i][j]=='.'&&j<n; j++,i--)
    {
        if(vis[i][j]==1)
            return 0;
    }
    return 1;
}
void dfs(int pos,int tmp)
{
    if(pos>=m)
        return ;
    if(res<tmp)
    {
        res=tmp;
    }
    pos++;
    dfs(pos,tmp);
    if(maps[pos/n][pos%n]=='.'&&judge(pos/n,pos%n))
    {
        vis[pos/n][pos%n]=1;
        dfs(pos,tmp+1);
        vis[pos/n][pos%n]=0;
    }
    return ;
}
int main()
{
    while(scanf("%d",&n),n)
    {
        res=0;
        memset(vis,0,sizeof(vis));
        for(int i=0; i<n; i++)
        {
            scanf("%s",maps[i]);
        }
        m = n*n;
        if(maps[0][0]=='.')
        {
            vis[0][0]=1;
            dfs(0,1);
            vis[0][0]=0;
        }dfs(0,0);
        printf("%d\n",res);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值