记录昨日搜索题目 (关于棋盘类搜索状态以及搜索顺序的思考)

对于一个棋盘类的题目,搜索方式有两种
第一种,让行作为搜索的一个参量,枚举列进行搜索
第二种,将坐标作为参量,一个点一个点搜

问题引入一:

在这里插入图片描述

分析 :

一道经典题目,此次将行作为参量,枚举列进行搜索,注意标记时对对角线的标记

#include <bits/stdc++.h>
using namespace std;

int n;
int res;

const int N = 110;
bool col[N], row[N], de[N], ude[N];

void dfs(int u) {

	if (u == n) {
		res++;
		return;
	}

	for (int i = 0; i < n; i++) {
		if (!row[u] && !col[i] && !de[i + u] && !ude[n - u + i]) {
			row[u] = col[i] = de[i + u] = ude[n - u + i] = 1;
			//cout << u << " " << i << endl;
			dfs(u + 1);
			row[u] = col[i] = de[i + u] = ude[n - u + i] = 0;
		}
	}
}

int main() {
	cin >> n;
	dfs(0);
	cout << res;
}

解释 de[u+i] ude[n-u+i]

将棋盘抽象为平面直角坐标系,于是对角线便是某一条直线。
不论对于正对角线,还是负对角线,每个正对角线或者副对角线的截距是独一无二的,可以用坐标 y+x 或者 y-x表示,由于y-x可能为负数,因此加上偏移量n即可表示

问题引入二:

在这里插入图片描述

题目解释:给个9*9不完整数独,填出来,保证唯一解

分析:

作为棋盘类搜索题目,与N皇后不同的是,他不再是一行一列只能填写一个,而是每个格子都需要填写,所以搜索的状态用(x,y)来表示,在考虑其他限制,就没有什么难度了
值得注意的只有如何dfs(x,y+1)等一系列细节操作

#include <bits/stdc++.h>
using namespace std;
const int N = 10;
bool col[N][N], row[N][N], Martix[N][N];
int f[N][N];
int belong[N][N];

void init() {
	for (int i = 1; i <= 9; i++) {
		for (int j = 1; j <= 9; j++) {
			if (i <= 3) {
				if (j <= 3)
					belong[i][j] = 1;
				else if (j <= 6)
					belong[i][j] = 2;
				else
					belong[i][j] = 3;
			} else if (i <= 6) {
				if (j <= 3)
					belong[i][j] = 4;
				else if (j <= 6)
					belong[i][j] = 5;
				else
					belong[i][j] = 6;
			} else {
				if (j <= 3)
					belong[i][j] = 7;
				else if (j <= 6)
					belong[i][j] = 8;
				else
					belong[i][j] = 9;
			}

		}

	}

}

void dfs(int x, int y) {

	if (y == 10)
		x++, y = 1;
	if (x == 10) {
		for (int i = 1; i <= 9; i++) {
			for (int j = 1; j <= 9; j++) {
				cout << f[i][j] << " ";
			}
			cout << endl;
		}
	}

	int ver = belong[x][y];
	if (f[x][y])
		dfs(x, y + 1);
	else
		for (int i = 1; i <= 9; i++) {
			if (!f[x][y] && !row[x][i] && !col[y][i] && !Martix[ver][i]) {
				//cout << x << " " << y << " " << i << endl;
				f[x][y] = i;
				row[x][i] = col[y][i] = Martix[ver][i] = 1;
				dfs(x, y + 1);
				row[x][i] = col[y][i] = Martix[ver][i] = 0;
				f[x][y] = 0;
			}
		}
}

int main() {
	init();
	for (int i = 1; i <= 9; i++) {
		for (int j = 1; j <= 9; j++) {
			int x;
			cin >> x;
			f[i][j] = x;
			row[i][x] = 1;
			col[j][x] = 1;
			int u = belong[i][j];
			Martix[u][x] = 1;
		}
	}
	dfs(1, 1);

}
  • 14
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值