MOOC清华《程序设计基础》第5章第2题:破损棋盘的八皇后问题

题目描述

8X8的国际象棋棋盘上被挖了一些洞,这些洞不能放棋子,求八皇后问题的摆放方案,输出一种方案即可

输入格式

棋盘用.表示正常格子,用#表示被挖掉的洞,一共8行8列

输出格式

输出从上到下的每一行的皇后所在列号(1-8)

注意:只输出列号,只输出列号,最后的输出应该只是8个数字,第i个数字表示第i行的皇后在第几列,中间以空格隔开。

样例输入

........
..##....
####....
........
........
........
........
....####
样例输出

6 2 7 1 4 8 5 3

#include <iostream>   
using namespace std;  
  
const int Normalize = 9;  //用来统一数组下标  
  
int Num = 0;  //方案数  
int q[9];  //8个皇后所占用的行号
char incomplete[9][9];  //记录残破棋盘的各个格子,注意是字符类型
  
bool C[9];  //S[1]~S[8],当前列是否安全  
bool L[17];  //L[2]~L[16],(i - j)对角线是否安全  
bool R[17];  //R[2]~R[16],(i + j)对角线是否安全  
  
void Try(int row)  
{  
    for(int col = 1; col <= 8; col++)  
    //依次尝试当前的8列位置  
    {  
        //判断拟放置皇后的位置是否安全  
        if(C[col] && L[row - col + Normalize] && R[row + col] && incomplete[row][col] != '#')  
        {  
            //记录位置信息(行号)  
            q[row] = col;  
              
            //修改三个方向的安全性标记  
            C[col] = false;  
            L[row - col + Normalize] = false;  
            R[row + col] = false;  
            //核心技巧其实在后面这两行里,只有这样调整,对角线的下标才  
            //统一地从2到16,两个方向的平行对角线都是15条   
              
            if(row < 8)  
            {  
                //递归尝试放下一行
                Try(row + 1);  
            }  
            else  
            {  
                Num++;  
            	if(Num == 1) 
                	for(int k = 1; k <= 8; k++)  
                    	cout << q[k] << " ";   
            }  
              
            //回溯:恢复三个方向原有安全性  
            C[col] = true;  
            L[row - col + Normalize] = true;   
            R[row + col] = true;  
        }   
    }   
}   
  
int main()  
{  
	for(int i = 0; i < 9; i++)  
		C[i] = true;  
    for(int i = 0; i < 17; i++)  
    {  
        L[i] = true;  
        R[i] = true;  
    } 
	    
    for(int i = 1; i < 9; i++)
    {
    	for(int j = 1; j < 9; j++)
    		cin >> incomplete[i][j];
	}
    
    Try(1);  //从第1行开始放皇后  
    
    return 0;   
}  



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值