首页 > 其他分享 >[USACO1.5] 八皇后 Checker Challenge 题解

[USACO1.5] 八皇后 Checker Challenge 题解

时间:2024-07-30 10:17:02浏览次数:11  
标签:输出 标记 题解 Challenge ans Checker 棋子 对角线 皇后

[USACO1.5] 八皇后 Checker Challenge

题目描述

一个如下的 \(6 \times 6\) 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

上面的布局可以用序列 \(2\ 4\ 6\ 1\ 3\ 5\) 来描述,第 \(i\) 个数字表示在第 \(i\) 行的相应位置有一个棋子,如下:

行号 \(1\ 2\ 3\ 4\ 5\ 6\)

列号 \(2\ 4\ 6\ 1\ 3\ 5\)

这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前 \(3\) 个解。最后一行是解的总个数。

输入格式

一行一个正整数 \(n\),表示棋盘是 \(n \times n\) 大小的。

输出格式

前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。

样例 #1

样例输入 #1

6

样例输出 #1

2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4

提示

【数据范围】
对于 \(100\%\) 的数据,\(6 \le n \le 13\)。

题目翻译来自NOCOW。

USACO Training Section 1.5

(一)读懂题目

(Who) 关键词

6×6棋盘
六个棋子
每行、每列
每条对角线
只有一个

(What) 关键词之间关键联系:

满足每行每列每个对角线只有一个棋子的棋局就是一种解法

(How) 思路:

(1)

分析:第一反应使用深度优先搜索去做,枚举每一行,对本次摆放的棋子的每一列和每一个对角线都标上记号

(2)

分析:我们可以运用标记数组,bool类型来进行标记

(3)

分析:重要的是对角线的标记问题,但经过观察可以发现,对角线不是i+j相等就是i-j+8相等,所以可以利用这个特性来进行标记

(二)分析时间+空间复杂度

时间复杂度:O(n)
空间复杂度:O(n)

(三)代码实现

#include<iostream>
#include<cstdio>
using namespace std;
int ans,n;//ans是用来记录输出次数,题目只要求输出3次 
int a[15];//每一行 
bool b[15],c[40],d[40];//标记数组,b数组标记那一列,c和d数组标记对角线 
void print()//打印函数 
{
	for(int j=1;j<=n;j++)
	{
		printf("%d ",a[j]);
	}
	puts("");
	return;
}
void dfs(int i)//重点:深搜dfs 
{
	if(i>n)//如果一种情况成立(i已经遍历完每一列所有位置) 
	{
		ans++;//记录+1 
		if(ans<=3)//如果<=3才输出,否则就是+1而已 
		{
			print();
		}
		return;
	}
	for(int j=1;j<=n;j++)//枚举每一列 
	{
		if(!b[j]&&!c[i+j]&&!d[i-j+n])//如果这个点没有被其他皇后给攻击到 
		{
			//标记ing …… 
			b[j]=true;
			c[i+j]=true;
			d[i-j+n]=true;
			a[i]=j;
			dfs(i+1);//继续深搜
			//取消标记,回溯ing…… 
			b[j]=false;
			c[i+j]=false;
			d[i-j+n]=false;
		}
	}
	return;
}
int main(){
	scanf("%d",&n);
	dfs(1);//记得从1开始 
	printf("%d\n",ans);
	return 0;
}

(四)总结反思

本题就是著名的八皇后问题,最初由国际西洋棋棋手马克斯·贝瑟尔于1848年提出的问题,是回溯算法的典型案例。
然后就是被许多人又改成了许多版本(N皇后、K皇后、皇后游戏、还是N皇后)……
呃,正事——
本题考察的是我们对与搜索的掌握,但对于本题而言,深搜dfs的回溯还是更适合枚举方案的
所以最后也是运用了dfs进行作答
AC~

标签:输出,标记,题解,Challenge,ans,Checker,棋子,对角线,皇后
From: https://www.cnblogs.com/Atserckcn/p/18331659

相关文章

  • 题解:P10815 【模板】快速读入
    闲着没事儿水篇tj题目大意题目大意极其粗暴,记得\(10^8\times10^8=10^{16}>2^{31}-1\)会爆int,开longlong就好。于是这个题就变成了一个读入输出优化模板题。这不又回去了。另外,输入输出常数优化也很常用,抢最优解和骗分时都可以用上。1cin/cout版本操作ios::......
  • 奇怪的汉诺塔 - 题解
    奇怪的汉诺塔时间限制:C/C++1000MS,其他语言2000MS内存限制:C/C++256MB,其他语言512MB描述汉诺塔问题,条件如下:这里有\(A\)、\(B\)、\(C\)和\(D\)四座塔。这里有\(n\)个圆盘,\(n\)的数量是恒定的。每个圆盘的尺寸都不相同。所有的圆盘在开始时都堆叠在塔\(A\)......
  • 昆虫繁殖 - 题解
    昆虫繁殖时间限制:C/C++1000MS,其他语言2000MS内存限制:C/C++256MB,其他语言512MB描述科学家在热带森林中发现了一种特殊的昆虫,这种昆虫的繁殖能力很强。每对成虫过\(x\)个月产\(y\)对卵,每对卵要过两个月长成成虫。假设每个成虫不死,第一个月只有一对成虫,且卵长成成虫后......
  • 【入门】汉诺塔的移动次数 - 题解
    【入门】汉诺塔的移动次数时间限制:C/C++1000MS,其他语言2000MS内存限制:C/C++128MB,其他语言256MB描述汉诺塔的问题大家都已经很熟悉了,有三个柱子,每个柱子上有一些大小不一的金片,要把金片从\(A\)柱移动到\(C\)柱,可以借助\(B\)柱,请问\(n\)个金片的情况下,需要最少移......
  • 【基础】递归问题—汉诺塔 - 题解
    【基础】递归问题—汉诺塔时间限制:C/C++1000MS,其他语言2000MS内存限制:C/C++127MB,其他语言254MB描述汉诺塔(又称河内塔)问题是印度的一个古老的传说。开天辟地的神勃拉玛在一个庙里留下了三根金刚石的棒,第一根上面套着\(64\)个圆的金片,最大的一个在底下,其余一个比一个小......
  • 放苹果 - 题解
    时间限制:C/C++1000MS,其他语言2000MS内存限制:C/C++256MB,其他语言512MB描述把\(M\)个同样的苹果放在\(N\)个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)\(5,1,1\)和\(1,5,1\)是同一种分法。输入描述第一行是测试数据的数目\(t\)(\(0≤t≤20\))。......
  • 【入门】统计每个月兔子的总数 - 题解
    【入门】统计每个月兔子的总数时间限制:C/C++1000MS,其他语言2000MS内存限制:C/C++16MB,其他语言32MB描述有一对兔子,从出生后第3个月起每个月都生一对兔子,一对小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第\(n\)个月(\(n<=50\))的兔子总数为多少对?输入描述......
  • 排序 - 题解
    排序时间限制:C/C++1000MS,其他语言2000MS内存限制:C/C++64MB,其他语言128MB描述给定你一个长度为\(n\)的整数数列。请你使用任意排序对这个数列按照从小到大进行排序。并将排好序的数列按顺序输出。数据范围\(1≤n≤100000\)禁止使用sort函数输入描述输入共两......
  • 逆序对的数量 - 题解
    逆序对的数量时间限制:C/C++1000MS,其他语言2000MS内存限制:C/C++64MB,其他语言128MB描述给定一个长度为\(n\)的整数数列,请你计算数列中的逆序对的数量。逆序对的定义如下:对于数列的第\(i\)个和第\(j\)个元素,如果满足\(i<j\)且\(a[i]>a[j]\),则其为一个逆序对;否则......
  • 求第k小的数 - 题解
    求第k小的数时间限制:C/C++1500MS,其他语言3000MS内存限制:C/C++256MB,其他语言512MB描述输入\(n\)个数字,输出这些数字的第\(k\)小的数。最小的数是第\(0\)小。输入描述第一行包含两个整数\(n(1≤n≤5000000)\)和\(k(0≤k<n)\)。输出描述1个整数(所有整数均在......