UVa 639:Don't Get Rooked, 类八皇后问题

题目链接:

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=108&page=show_problem&problem=580

题目类型: 暴力, 回溯法

题目:

In chess, the rook is a piece that can move any number of squares vertically or horizontally. In this problem we will consider small chess boards (at most 4

4) that can also contain walls through which rooks cannot move. The goal is to place as many rooks on a board as possible so that no two can capture each other. A configuration of rooks is legalprovided that no two rooks are on the same horizontal row or vertical column unless there is at least one wall separating them.

The following image shows five pictures of the same board. The first picture is the empty board, the second and third pictures show legal configurations, and the fourth and fifth pictures show illegal configurations. For this board, the maximum number of rooks in a legal configuration is 5; the second picture shows one way to do it, but there are several other ways.

Your task is to write a program that, given a description of a board, calculates the maximum number of rooks that can be placed on the board in a legal configuration.

Sample Input

4
.X..
....
XX..
....
2
XX
.X
3
.X.
X.X
.X.
3
...
.XX
.XX
4
....
....
....
....
0

Sample Output

5
1
5
2
4

题意:

在象棋中,“车”是可以在棋盘上沿着纵向或横向走任意格子的棋子。 在这个问题中,我们假设有一个4*4的小棋盘,

在这个棋盘上面包含着“墙”,而“车”是不能越过墙的。而我们的目标就是尽可能地放置更多地“车”到这个棋盘上去,使所有

的这些”车“互相不能吃到其它棋子。

在上面几副图中给出了几个样例, 棋盘上,格子全部是黑色的代表是“墙”, 黑色圆形的代表是“车”。

其中第二,三副图的棋子的放置是正确的,第四,五副图的棋子是错误的,因为那两个棋子可以互相吃到对方。

分析与总结:

做这题不得不说一下非常非常非常非常经典的、只要是有讲回溯法的算法书都会讲到的“八皇后问题”。

“八皇后问题”是一个古老而著名的问题,是回溯算法的典型例题,具体是:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

而这题,区别在于要求变成了任意两个“车”不能同一行、同一列,但是增加了如果有“墙”隔开的话,就可以在同行或同列。

基本上,就是解决这个问题的方法,也就是解决八皇后问题的方法,只要判断条件改变一下。所以这个问题称这题为

类八皇后问题。

解法一:暴力枚举法

把这个问题转变为,“从4*4的格子中选择一个子集”,这个子集表示那些格子放置了棋子,那些格子没有放置格子,

找到符合条件的、放置棋子数量最多的那么子集,便是答案了。

对于棋盘上的格子,有两种状态:放或者不放。那么,便很容易想到用0和1来表示状态。既然是0和1,我们可以进一步

用2进制的来表示。4*4共有16个格子,我们需要一个16位的二进制,

即0000000000000000~1111111111111111, 换算成十进制就是0~2^16-1, 我们可以用一个十进制的数,让他从0开始,

一直加到2^16-1, 就是遍历了棋盘所有可能的情况。过程中,只需要根据这个数字的二进制状态来判断那些格子是有放置

棋子,那些格子是没有放置格子了。可以另外开一个数组专门来保存这种状态。

对于每一个子集,我们需要判断这个子集的放置是否符合要求。只需要遍历一边,对于每个放置的格子判断它是否和其他

棋子有没有冲突即可。

详细代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define MAXN 6
using namespace std;
char map[MAXN][MAXN];
int dir[4][2] = {{0,1},{0,-1},{1,0},{-1,0}};
int status[MAXN*MAXN], Max, n;  

// 把二进制转换为状态
bool change(int x){
    int pos = n*n-1;
    if(x==-1) return false;
    while(pos>=0){
        status[pos] = (x & 1);
        x >>= 1;
        --pos;
    }
    return true;
}  

// 判断那个点是否有冲突
bool isConflict(int row, int col){  

    for(int i=0; i<4; ++i){
        int dx = row+dir[i][0];
        int dy = col+dir[i][1];
        while(dx>=0 && dx<n && dy>=0 && dy<n){
            if(map[dx][dy]=='X') break;
            if(status[dx*n+dy]) return true;
            dx += dir[i][0];
            dy += dir[i][1];
        }
    }
    return false;
}  

// 判断这种放置方案是否可行
bool judge(){  

    for(int i=0; i<n; ++i){
        for(int j=0; j<n; ++j){
            if(status[i*n+j] && map[i][j]=='X'){
                return false;
            }
            if(status[i*n+j]){ // 如果有放置棋子,判断他四个方向是否有放置
                if(isConflict(i, j)) return false;
            }
        }
    }
    return true;
}  

int main(){
#ifdef LOCAL
    freopen("input.txt","r",stdin);
#endif
    while(~scanf("%d", &n) && n){  

        for(int i=0; i<n; ++i)
            scanf("%s", map[i]);  

        int xx = (1<<(n*n))-1;  

        int maxNum = -2147483645;
        while(change(xx--)){
            if(judge()){
                int sum = 0;
                for(int i=0; i<n*n; ++i)
                    if(status[i]) ++sum;
                if(sum > maxNum) maxNum = sum;
            }
        };  

        printf("%d\n", maxNum);
    }
    return 0;
}

解法二:递归回溯

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索问题
, 八皇后
, n皇后 内存溢出
, swift问题算法八皇后ios
, 子集和的小问题
, 一个
, The
, n皇后问题
, 棋盘
, 八皇后问题
, 子集
, n皇后
格子
grooked、overooked键盘卡、八皇后问题、八皇后、八皇后问题 c语言,以便于您获取更多的相关知识。

时间: 2024-08-22 14:22:12

UVa 639:Don't Get Rooked, 类八皇后问题的相关文章

UVa 639 Don&#039;t Get Rooked:DFS好题

639 - Don't Get Rooked Time limit: 3.000 seconds http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=108&page=show_problem&problem=580 In chess, the rook is a piece that can move any number of squares vertically o

基于Delphi的八皇后问题动态实现

摘要 对于八皇后问题的实现,如果结合动态的图形演示,则可以使算法的描述更形象.更生动,使教学能产生良好的效果. 关键词 八皇后问题 冲突 数据结构 线程类 八皇后问题是一个古老而著名的问题,是回溯算法的典型例题.该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 下面用delphi6实现的八皇后问题的动态图形程序,能够演示全部的92组解.八皇后问题动态图形的实现,主要应解决以下

UVa 167:The Sultan&#039;s Successors, 八皇后问题

题目链接: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=108&page=show_problem&problem=103 题目类型: 回溯 原题: The Sultan of Nubia has no children, so she has decided that the country will be split into up to k separate

面试题:八皇后问题(N皇后问题)

前言 八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?这道题目也可以稍微延伸一下,变为 N×N的棋盘上放置N个皇后,其他条件相同. 下面介绍一种比较简单易懂的实现方式. 项目下载地址 正文 算法 先说一下算法, 这里使用的是一个改良版的广度优先搜索算法.在N×N的棋盘上,我们先在第一行的第一个位置放置下皇后,接着我们就不去管第一行了,因为第一行已经不能放置皇后了.我们在第二行找到所有的可以放置皇后的位置.同理我们

C++实现八皇后问题的方法_C 语言

本文实例展示了C++实现八皇后问题的方法,是数据结构与算法中非常经典的一个算法.分享给大家供大家参考之用.具体方法如下: 一般在八皇后问题中,我们要求解的是一个8*8的国际象棋棋盘中,放下8个皇后且互相不能攻击的排列总数.皇后的攻击范围为整行,整列,以及其斜对角线. 由于皇后的攻击范围特性,注定我们每行只能放下一个皇后,于是我们要做的只是逐行放下皇后.八皇后问题是回溯法的典型问题.这里我们用的方法很简单: 从第一行开始逐个检索安全位置摆放皇后,一旦有安全位置则考虑下一行的安全位置.如果发现某行没

八皇后问题的C#解答

解答|问题 改编自V星[视窗王子]应答程序,如下:<br><br>using System;<br>class Queen{<br>    const int SIZE = 8;//皇后数<br>    public static void Main()<br>    {<br>        int[] Queen = new int [SIZE];//每行皇后的位置<br>        int y,x,i

常用算法:C#八皇后问题

八皇后问题是一个古老而著名的问题,是回溯算法的典型应用.八皇后问题就是棋盘上的8个皇后不能在同一行.一列或一条斜线上,在8!=40320种排列中共有92种解决方案.代码如下: using System; using System.Collections.Generic; using System.Text;namespace ExQueen { class Queen { public void QueenArithmetic(int size){ int[] Queen = new int[s

python基于右递归解决八皇后问题的方法

  本文实例讲述了python基于右递归解决八皇后问题的方法.分享给大家供大家参考.具体分析如下: 凡是线性回溯都可以归结为右递归的形式,也即是二叉树,因此对于只要求一个解的问题,采用右递归实现的程序要比回溯法要优美的多. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 def Test(queen,n): '''这个就不用说了吧,就是检验第n(下标,0-7)行皇后的位置是否合理''' q=que

javascript递归回溯法解八皇后问题

  javascript递归回溯法解八皇后问题:           网上看到许多关于八皇后算法的文章,很少能看到使用javascript来实现的,今天就给大家使用javascript来解决下这个问题,有需要的小伙伴可以参考下. 下面给大家分享的是回溯法解八皇后, 带详细注解,这里就不多废话了. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36