其他刷题记录

某笔试的题目:

锯齿数独3x3

简单来说就是给你一个填了某些字的数独,告诉你哪3个点属于一个宫,然后同行同列同宫不能有重复。

接下来给定几组数据,判断是否有解,唯一解则输出Unique和该解,多解则输出Mutiple,无解输出无解。

思路:

经典的矩阵型,dfs遍历的方式。自己写的时候遇上了几个问题,现在在此总结一下。

3行3列代表数独信息,下面3行,每行代表一个宫的三个点。

输入数据如下:

4
*2*
1*2
***
0 0 0 1 1 0
0 2 1 1 1 2
2 0 2 1 2 2

遍历的方式:使用dfs遍历,然后上下左右遍历,

如果点超过边界则返回。

如果访问过则返回。防止再次访问。

对于点有两种情况,一种是没有赋值的点,那我们就赋值,赋值时从1到3依次判断,判断该点是否满足行列宫没有重复。

已有值的点,那么无需再访问,直接返回即可

(一开始我是这么想的,发现不能这样:原因如下:

例如:

这个左上角的点去dfs遍历时,右边和下面的点都已赋值,如果直接返回,会出现dfs直接无法遍历整个图。因为(0,0)这个点与外界不连通。因此为了实现走出外面,即使该值有点也要进行向外dfs:

这样即可保证dfs一次初始点(0,0)一定能遍历完整张图。

上面是对于该点已有值的情况,接下来介绍对于该点没有值的情况:

如果没有值就从1到3依次往里面试看是否满足同行同列同宫没有相同的数,找到第一个成功的数就填入。

填入之后则将checkNum++(checkNum是记录已经填满的数字个数)。 

找到了一个点之后,我们就以此为基础,继续dfs:如下图红框所示

而当dfs结束时,也就是回溯后, 需要将值返回成原来的样子:如下图红框所示

那么如何判断是否找到解?找到解之后需要做什么?

判断是否找到解的方式比较简单,只需要在填入数字,增加checkNum时,判断是否为9:

找到解后,将ans的值++。

由于单解情况下需要输出解,而回溯时会把填的数字清空,所以我们需要把该解记录下来,用一个successArray。

此处如何判断多解的思路?

此处无需找出全部解,只需要判断是否是多解即可。

因此,如果找到了一个解,那么只需要将这个解记录下来,然后之后如果找到了解(即checkNum为9)的话,就判断这两个解是否相同,如果不相同则说明有多解。

代码如下:

#include<iostream>
using namespace std;
class Point {
public:
	int x, y;
	Point() {
	}
	Point(int x1, int y1) {
		x = x1, y = y1;
	}
};
class GongClass {
public:
	Point gongPoint[3];
};

class ShuDu {
	int array[3][3];
	bool visit[3][3];
	GongClass Gong[3];
	int checkNum = 0;//已经写完的数
	int successArray[3][3];
public:
	int hasAns = 0;
	void ShuDuInit() {
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				char num;
				cin >> num;
				if (num != '*') {
					checkNum++;
					array[i][j] = int(num - '0');
				}
				else array[i][j] = 0;
				visit[i][j]=false;
			}
		}

		for (int i = 0; i < 3; i++) {

			for (int k = 0; k < 3; k++) {
				int x, y;
				cin >> x >> y;
				Point point;
				point.x = x;
				point.y = y;
				Gong[i].gongPoint[k] = point;
			}

		}


		//dfsCheck(Point(0, 0));

		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				cout << "dfsPoint:" << i << " " << j << endl;
				printArray();
				dfsCheck(Point(i, j));
			}
		}
		/*cout << checkNum << endl;
		cout << hasAns << endl;*/
	}

	bool CheckRow(Point point, int num) {
		int x = point.x;
		int y = point.y;
		for (int j = 0; j < 3; j++) {
			if (array[x][j] == num) {
				//cout << "chongfuRow" << x << " " << j << endl;
				return false;
			}
		}
		return true;
	}
	bool CheckCol(Point point, int num) {

		int x = point.x;
		int y = point.y;
		for (int i = 0; i < 3; i++) {
			if (array[i][y] == num) {
				//cout << "chongfuCol " << i << " " << y << endl;
				//cout << "array i y:"<<array[i][y] << endl;
				return false;
			}
		}
		return true;
	}

	bool CheckGong(Point point, int num) {
		GongClass pointInGong = findGong(point);
		for (int i = 0; i < 3; i++) {
			int x = pointInGong.gongPoint[i].x;
			int y = pointInGong.gongPoint[i].y;
			if (array[x][y] == num)return false;
		}
		return true;
	}

	GongClass findGong(Point point) {
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				if (Gong[i].gongPoint[j].x == point.x&&Gong[i].gongPoint[j].y == point.y)
					return Gong[i];
			}
		}

		return Gong[0];
	}

	void dfsCheck(Point point) {
		int x = point.x;
		int y = point.y;
		if (point.x < 0 || point.x >= 3 || point.y < 0 || point.y >= 3)return;
		if (visit[x][y] == true)return;

		/*if (visit[x+1][y] == false)dfsCheck(Point(x + 1, y));
		if (visit[x][y+1] == false)dfsCheck(Point(x, y + 1));
		if (visit[x - 1][y] == false)dfsCheck(Point(x - 1, y));
		if (visit[x][y-1] == false)dfsCheck(Point(x, y - 1));*/

		//cout << "point.x:" << x << " point.y:" << y << endl;

		visit[x][y] = true;//进入一个点则设置访问

		bool checkFlag = false;//检查是否有满足的数字可以填入
		if (array[x][y] == 0) {
			for (int index = 1; index <= 3; index++) {
				//检查该数字是否满足每行每列每宫的要求
				if (CheckRow(point, index) && CheckCol(point, index) && CheckGong(point, index)) {
					array[point.x][point.y] = index;
					checkNum++;

					checkFlag = true;
					cout << "success Point [" << x << "][" << y << "]"<< ":" << index << endl;
					if (checkNum == 9) {
						hasAns++;
						if (hasAns > 1) {
							if (checkSameArray()) {
								cout << "SameArray" << endl;
								hasAns--;
								break;
							}
						}
						cout << "hasAns" << endl;

						//由于回溯时会删去visit的记录和做好标记的结点,所以需要删除值,但是因为需要打印,所以需要将该成功的值保存
						for (int i = 0; i < 3; i++) {
							for (int j = 0; j < 3; j++)
								successArray[i][j] = array[i][j];
						}
						printArray();


					}


					//dfsCheck(Point(x + 1, y));
					//dfsCheck(Point(x, y + 1));
					//dfsCheck(Point(x - 1, y));
					//dfsCheck(Point(x, y - 1));

					//array[point.x][point.y] = 0;
					//checkNum--;
					//visit[x][y] = false;
					break;

					
				}
			}
		}
		else {
			//visit[x][y] = true;
			dfsCheck(Point(x + 1, y));
			dfsCheck(Point(x, y + 1));
			dfsCheck(Point(x - 1, y));
			dfsCheck(Point(x, y - 1));
			return;
		}


		//如果里面不能填入数字,说明前一步有问题,因此应该要返回,并且重置访问
		if (checkFlag == false) {
			visit[x][y] = false;
			return;
		
		}


		dfsCheck(Point(x + 1, y));
		dfsCheck(Point(x, y + 1));
		dfsCheck(Point(x - 1, y));
		dfsCheck(Point(x, y - 1));

		array[point.x][point.y] = 0;
		checkNum--;
		visit[x][y] = false;


		return;
	}

	void printSuccessArray() {
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				cout << successArray[i][j];
			}
			cout << endl;
		}
	}

	void printArray() {
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				cout << array[i][j];
			}
			cout << endl;
		}
	}

	bool checkSameArray() {
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				if (array[i][j] != successArray[i][j])return false;
			}
		}
		return true;
	}

};


int main() {

	int t;
	cin >> t;
	while (t--) {
		ShuDu shuDu;
		shuDu.ShuDuInit();
		if (shuDu.hasAns == 1) {
			cout << "Unique" << endl;
			shuDu.printSuccessArray();
		}
		else if(shuDu.hasAns>1){
			cout << "Multiple" << endl;
		}
		else cout << "NO"<<endl;
	}
};

	

/*

1
*2*
1*2
***
0 0 0 1 1 0
0 2 1 1 1 2
2 0 2 1 2 2


4
*2*
1*2
***
0 0 0 1 1 0
0 2 1 1 1 2
2 0 2 1 2 2
**3
***
***
0 0 1 0 1 1
0 1 0 2 1 2
2 0 2 1 2 2
**3
1**
**2
0 0 1 0 1 1
0 1 0 2 1 2
2 0 2 1 2 2
3*3
1**
**2
0 0 1 0 1 1
0 1 0 2 1 2
2 0 2 1 2 2


*/

猜你喜欢

转载自blog.csdn.net/weixin_43757333/article/details/123570128