回朔法求数独

你一定听说过“数独”游戏。

如【图1.png】,玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个同色九宫内的数字均含1-9,不重复。

数独的答案都是唯一的,所以,多个解也称为无解。

本图的数字据说是芬兰数学家花了3个月的时间设计出来的较难的题目。但对会使用计算机编程的你来说,恐怕易如反掌了。

本题的要求就是输入数独题目,程序输出数独的唯一解。我们保证所有已知数据的格式都是合法的,并且题目有唯一的解。

格式要求,输入9行,每行9个数字,0代表未知,其它数字为已知。

输出9行,每行9个数字表示数独的解。

例如:

输入(即图中题目):

005300000

800000020

070010500

400005300

010070006

003200080

060500009

004000030

000009700

程序应该输出:

145327698

839654127

672918543

496185372

218473956

753296481

367542819

984761235

521839764

再例如,输入:

800000000

003600000

070090200

050007000

000045700

000100030

001000068

008500010

090000400

程序应该输出:

812753649

943682175

675491283

154237896

369845721

287169534

521974368

438526917

796318452

资源约定:

峰值内存消耗 < 256M

CPU消耗  < 2000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

//数独问题

#    include <iostream>
#    include <cstring>
#    include <fstream>
using namespace std;
int map[9][9];
void display(){
	int i,j;
	for(i=0;i<9;i++){
		for(j=0;j<9;j++){
			cout<<map[i][j]<<" ";
		}
		cout<<endl;
	}
}
bool check(int c){
	int x,y,i,j,dx,dy;
	x=c/9;
	y=c%9;
	for(i=0;i<9;i++){
		if(map[i][y]==map[x][y]&&x!=i)
			return false;
	}
	for(j=0;j<9;j++){
		if(map[x][j]==map[x][y]&&y!=j)
		return false;
	}
	dx=x/3*3;
	dy=y/3*3;
	for(i=dx;i<dx+3;i++){
		for(j=dy;j<dy+3;j++){
			if(map[i][j]==map[x][y]&&i!=x&&j!=y)
				return false;
		}
	}
	return true;
}
void backtrack(int n){
	int x,y;
	if(n==81){
		//if(check(80))
		display();
		cout<<endl;
		return ;
	}
	x=n/9;
	y=n%9;
	if(map[x][y]==0){
		for(int k=1;k<=9;k++){
			map[x][y]=k;
			if(check(n)){
				backtrack(n+1);
			}
			map[x][y]=0;         //请注意此处应当清零,如果不清零下一次就没有办法触发!!!
		}
		map[x][y]==0;
		return;
	}
	else{
		backtrack(n+1);
	}
}
int main(){
	int i,j;
	fstream in("shudu.txt");
	for(i=0;i<9;i++){
		for(j=0;j<9;j++){
			in>>map[i][j];
		}
	}
	backtrack(0);
	return 0;
}

注意: main函数需要返回0

注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。

注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型。

用回朔法求数独的运算理解上是挺简单的,写起来的时候注意一下几个要点,就不会有什么问题了,下面是我的代码,没有优化过,如果有什么不妥的地方请评论或者私信

时间: 2024-10-12 13:16:55

回朔法求数独的相关文章

回朔法/KMP算法-查找字符串

回朔法:在字符串查找的时候最容易想到的是暴力查找,也就是回朔法.其思路是将要寻找的串的每个字符取出,然后按顺序在源串中查找,如果找到则返回true,否则源串索引向后移动一位,再重复查找,直到找到返回true,或者源串查找完也没有找到返回false:这种方法简单粗暴,但思路清晰.又因为每次查找失败,源串需要回到起始位置的下一个位置开始查找,所以该算法也称为回朔法. KMP算法:先对要查找的字符串进行分析,找出其中重复的子字符串.然后将目标串与源串比较,一旦比较失败,则不用回朔,而是根据目标串子串的

【经典算法】回朔法

回溯是遍历所有搜索空间所有可能组态的方法.这些组态也许代表对象的所有排列或这是构建对象集合的所有可能的方法(子集).其他情况包括列举一个图的所有生成树,两个节点的所有路径或是把节点分类成不同颜色的所有不同的方式. 这些问题有一个共同的难点就是我们必须每次产生一个可能的组态.避免重复或遗漏组态的方法就是我们必须定义一个系统性的产生组态的顺序.我们把组合搜索解作为一个向量a=(a1,a2,...,an),向量元素ai来自有限子集S.这样的向量也许表示一个序列,元素ai是排列的第i个元素.或者,向量表

翻牌回朔法解题

#include <cstdlib> #include <iostream> using namespace std; class card{ private: int a[5][5];//原题 int b[5][5];//解决方案 int c[5][5];//桥 int s[5][5];//结果串 int counts;//解数目 public: card (char x[25]); void Backtrack (int t); bool Constraint(int t);

递归之回朔算法应用----八皇后问题

从前,有个皇帝,取了八个皇后,由此产生一系列乱七八糟的问题,八皇后问题由此产生.哈哈 开个玩笑~~~~ 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 高斯认为有76种方案.1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果.计算机发明后,有多种方法可以解决此问题.

筛选法求素数

筛选法求素数,不断的用3,5,7,等素数作为筛子,筛除这些数的倍数,即将合数筛除.用辅助数组p记录数i是否是素数. vector<int> prime(int n) { vector<int> p(n+1); for(int i=2;i<=n;i+=2) { if(i%2==0&&i>2) p[i]=0; else p[i]=1; } for(int i=3;i<=(int)(sqrt((double)n));i+=2) { if(p[i]) fo

欧几里得算法求最大公约数(gcd)

关于欧几里得算法求最大公约数算法, 代码如下: int gcd( int a , int b ) { if( b == 0 ) return a ; else gcd( b , a % b ) ; } 证明: 对于a,b,有a = kb + r  (a , k , b , r 均为整数),其中r = a mod b . 令d为a和b的一个公约数,则d|a,d|b(即a.b都被d整除), 那么 r =a - kb ,两边同时除以d 得 r/d = a/d - kb/d = m (m为整数,因为r也

BZOJ 1057: [ZJOI2007]棋盘制作 悬线法求最大子矩阵+dp

1057: [ZJOI2007]棋盘制作 Description 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳.而我们的主人公小Q,正是国际象棋的狂热爱好者.作为一个顶尖高手,他已不满足于普通的棋盘与规则,于是他跟他的好朋友小W决定将棋盘扩大以适应他们的新规则.小Q找到了一张由N*M个正方形的格子组成的矩形纸片,每个格子被涂有黑白两种颜色之一.小Q想在这种纸中裁减

【算法】普通方法和筛选法求素数

素数指的是因子只有1和本身的数(1不是素数),求解素数在数学上应用非常广泛,而求解n以内的素数也是我们编程时常遇到的问题,在这个问题上,筛选法求解素数运行得非常快.下面首先介绍如何判断一个是不是素数,然后介绍用普通方法求n以内的素数,接着是筛选法求n以内的素数,最后是两种算法的运行时间比较 判断一个数是不是素数 算法思想:判断小于等于一个数的平方的所有大于1的整数是不是能整除这个数,如果能,则表明这个数不是素数:反之,则是素数. //判断一个数是否为素数 bool isPlain(int val

欧几里得算法求两个整数的最大公因数

unsigned int Gcd (unsigned int m,unsigned int n){ unsigned int rem; while(n>0){ rem = m % n; m = n; n = rem; } return m; } 对于m<n的情况,第一次循环m,n会交换 算法的时间复杂度计算 时间复杂度 logn 若M > N,则第一次循环交换M和N. 若想分析其时间复杂度,则要求循环次数,即生成余数的次数. 可以证明: 当M > N, 则M % N < M