zoukankan      html  css  js  c++  java
  • 双倍快乐:两个八皇后:ybt1213&ybt1214

    ybt1213 八皇后 & ybt1214 八皇后

    ybt1213

    【题目描述】

    在国际象棋棋盘上放置八个皇后,要求每两个皇后之间不能直接吃掉对方。

    【无输入】

    【输出】

    按给定顺序和格式输出所有八皇后问题的解(见样例)。
    【输出样例】

    No. 1
    1 0 0 0 0 0 0 0 
    0 0 0 0 0 0 1 0 
    0 0 0 0 1 0 0 0 
    0 0 0 0 0 0 0 1 
    0 1 0 0 0 0 0 0 
    0 0 0 1 0 0 0 0
    0 0 0 0 0 1 0 0 
    0 0 1 0 0 0 0 0 
    No. 2
    1 0 0 0 0 0 0 0
    0 0 0 0 0 0 1 0
    0 0 0 1 0 0 0 0
    0 0 0 0 0 1 0 0
    0 0 0 0 0 0 0 1
    0 1 0 0 0 0 0 0
    0 0 0 0 1 0 0 0
    0 0 1 0 0 0 0 0
    ...以下省略
    

    【题解】

    每个皇后可以吃掉所在行,列,斜线共八个方向的棋子,国际象棋棋盘共有八行八列,有2*15个斜线因此八皇后问题的策略就是在每一行,每一列,有且只有一个皇后,并且任意两个皇后不在同一斜线。

    观察样例,不难发现是以每一列皇后的所在行数升序排列的,(参考ybt1214,不过与其相反,ybt1214是以每一行的列数升序排列的)所以就可以这样分类讨论。

    这时就可以确定方向,从左往右一列一列的枚举,在每一列分别枚举不同可行的皇后位置,每当假设一个位置有皇后,那就将她右边的控制点(控制点是什么?可以参考过河卒)打上标记,并且随着皇后的变化不断更新,这样就可以使以后的皇后有正确的可行位置。

    这就是思路,算法还是要在代码中体现。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int num=0;
    bool a[30][30]={0},b[30][30]={0};//a是方案棋盘,也就是存皇后的位置;b是控制棋盘,存当前能放或不能放皇后的位置
    void print() {//打印方案,不用多说
    	printf("No. %d
    ",++num);//别忘了空格
    	for(int i=1;i<=8;i++) { 
    		for(int j=1;j<=8;j++)
    			printf("%d ",int(a[i+10][j+10]));//加10的原因在后面第28行
    		printf("
    ");
    	}
    	return;
    }
    void dfs(int x,int y) {//x是当前已经决定的皇后的所在行,y是当前已经决定的皇后的所在列 
    	a[x+10][y+10]=1;//首先使方案中本格有皇后
    	if(y==8) {//列数到了最右边
    		print();//可以输出
    		a[x+10][y+10]=0;//由于已经输出方案,所以需要继续搜索,此皇后位置要空出来
    		return; 
    	}
    	bool z[30][30]={0};//这是对控制棋盘起备份作用的备份棋盘,用于之后还原操作
    	for(int k=1;y+k<=8;k++) {
    		z[x+10][y+k+10]=b[x+10][y+k+10];//备份
    		z[x+k+10][y+k+10]=b[x+k+10][y+k+10];
    		z[x-k+10][y+k+10]=b[x-k+10][y+k+10];
    		b[x+10][y+k+10]=1;//控制她右边可控制的格子
    		b[x+k+10][y+k+10]=1;//由于这里+k以及下面-k,所以数组可能超限(10*10),所以把数组改为(30*30),并将元素都向后移10位避免超限,这就是所有下标都加10的原因
    		b[x-k+10][y+k+10]=1;
    	}
    	for(int k=1;k<=8;k++) {//开始枚举
    		if(!(b[k+10][y+11])) {//格子未被控制
    			dfs(k,y+1);//在(k,y+1)放置皇后
    		}
    	}
    	for(int k=1;y+k<=8;k++) {//还原
    		b[x+10][y+k+10]=z[x+10][y+k+10];
    		b[x+k+10][y+k+10]=z[x+k+10][y+k+10];
    		b[x-k+10][y+k+10]=z[x-k+10][y+k+10];
    	}
    	a[x+10][y+10]=0;//和19行类似,再把这个皇后拿走
    	return;
    }
    int main() {
    	for(int l=1;l<=8;l++)
    		dfs(l,1);//枚举第一个皇后的位置
    	return 0; 
    }
    

    做这道题时,我遇到几个问题:

    1.玄学的t变量

    在一开始,本来想打个标记,判断无解跳出,在现在的第30行的后面建了一个t变量。最后,程序调好了,t也没用了,但是当我删掉t了以后,程序无输出,调试发现根本没有执行17行的if语句。然后又加上t,还是不行。吓得我赶紧撤销,撤回t还在的情况,唯一的区别是之前的t有赋值0。当t有赋值时,程序正常输出,无论赋值多少。

    最后只能带着t提交,结果re,发现是爆数组了,因为皇后的斜着走操作有可能爆10*10的数组,最后数组扩大才解决。

    2.格式出错

    终于调好了程序的我再次提交,结果格式错误,仔细查看样例发现“No.”里的“.”后面是有空格的,又贡献了一次的KD

    ybt1214

    【题目描述】

    会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(有8 × 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。

    对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b1b2...b8a=b1b2...b8,其中bi为相应摆法中第i行皇后所处的列数。已经知道8皇后问题一共有92组解(即92个不同的皇后串)。

    给出一个数b,要求输出第b个串。串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时比y小。

    【输入】

    第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数b(1≤b≤92)。

    【输出】

    输出有n行,每行输出对应一个输入。输出应是一个正整数,是对应于b的皇后串。

    【输入样例】

    2 1 92
    

    【输出样例】

    15863724
    84136275
    

    【题解】

    在上一题的基础上把打印方案改为存储方案即可

    注意!由于方案的对称性,所以虽然优先级不同,但还是可以通用之前的方案顺序。(务必先看ybt1213)

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int num=0,c,n,ans[100][30];
    bool a[30][30]={0},b[30][30]={0};
    void record() {
    	++num;
    	for(int i=1;i<=8;i++) { 
    		for(int j=1;j<=8;j++)
    			if(a[i+10][j+10])
    				ans[num][j+10]=i;
    	}
    	return;
    }
    void dfs(int x,int y) {
    	a[x+10][y+10]=1;
    	if(y==8) { 
    		record();
    		a[x+10][y+10]=0;
    		return; 
    	}
    	bool z[30][30]={0};
    	for(int k=1;y+k<=8;k++) {
    		z[x+10][y+k+10]=b[x+10][y+k+10];
    		z[x+k+10][y+k+10]=b[x+k+10][y+k+10];
    		z[x-k+10][y+k+10]=b[x-k+10][y+k+10];
    		b[x+10][y+k+10]=1;
    		b[x+k+10][y+k+10]=1;
    		b[x-k+10][y+k+10]=1;
    	}
    	for(int k=1;k<=8;k++) {
    		if(!(b[k+10][y+11])) {
    			dfs(k,y+1);
    		}
    	}
    	for(int k=1;y+k<=8;k++) {
    		b[x+10][y+k+10]=z[x+10][y+k+10];
    		b[x+k+10][y+k+10]=z[x+k+10][y+k+10];
    		b[x-k+10][y+k+10]=z[x-k+10][y+k+10];
    	}
    	a[x+10][y+10]=0;
    	return;
    }
    int main() {
    	cin>>n;
    	for(int l=1;l<=8;l++)
    		dfs(l,1);
    	for(int m=1;m<=n;m++) {
    		cin>>c;
    		for(int o=1;o<=8;o++)
    			cout<<ans[c][o+10];
    		cout<<endl; 
    	}
    	return 0; 
    }
    
  • 相关阅读:
    516. Longest Palindromic Subsequence最长的不连续回文串的长度
    java之spring之整合ssh-2
    java之spring之整合ssh
    java之spring之spring整合hibernate
    微服务之初了解(一)
    java之spring之scope和autowiring
    java之spring之依赖注入
    java之spring之对象的创建
    java之spring之配置讲解
    asp.net core 系列之静态文件
  • 原文地址:https://www.cnblogs.com/Wild-Donkey/p/12238957.html
Copyright © 2011-2022 走看看