数独——拥有一定难度的回溯练习题,值得一看

数独相信大家都玩过,也都拥有不同的策略,那么放到C++中又是怎样的呢?其实它就是回溯算法。话不多说,直接用例题来讲解:

Description

数独是根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫内的数字均含1−9且不重复。每一道合格的数独谜题都有且仅有唯一答案,推理方法也以此为基础,任何无解或多解的题目都是不合格的。

芬兰一位数学家号称设计出全球最难的“数独游戏”,并刊登在报纸上,让大家去挑战。

这位数学家说,他相信只有“智慧最顶尖”的人才有可能破解这个“数独之谜”。

据介绍,目前数独游戏的难度的等级有一到五级,一是入门等级,五则比较难。不过这位数学家说,他所设计的数独游戏难度等级是十一,可以说是所以数独游戏中,难度最高的等级。他还表示,他目前还没遇到解不出来的数独游戏,因此他认为“最具挑战性”的数独游戏并没有出现。

Format

Input

一个未填的数独。

Output

填好的数独。

这道题是洛谷上的原题数独 - 洛谷

看着题很长,其实一点也不难,只需要一个点一个点的枚举加上回溯就可以了,再开三个数组来记录当前这一行和这一列以及再一个3*3的格子里的数字的剩余形况。

ACcode

 

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

int h[10][10],l[10][10],a[10][10],ans[10][10],g[5][5][10],cmp;

void dfs(int x,int y){
	if (cmp==1)return;
	if (x==10&&y==1){
		for (int i=1;i<=9;i++){
			for (int j=1;j<=9;j++){
				cout<<ans[i][j]<<" ";
			}
			cout<<endl;
		}
		cmp=1;
		return;
	}
	
	if (a[x][y]!=0){
		ans[x][y]=a[x][y];
		if (y==9){
			dfs(x+1,1);
		}else {
			dfs(x,y+1);
		}
		return;
	}else {
		for (int i=1;i<=9;i++){
			if (h[x][i]==0&&l[y][i]==0&&g[(x-1)/3+1][(y-1)/3+1][i]==0){
				h[x][i]=1;
				l[y][i]=1;
				g[(x-1)/3+1][(y-1)/3+1][i]=1;
				ans[x][y]=i;
				//
				if (y==9){
					dfs(x+1,1);
				}else {
					dfs(x,y+1);
				}
				//
				h[x][i]=0;
				l[y][i]=0;
				g[(x-1)/3+1][(y-1)/3+1][i]=0;
			}
		}
	}

	return;
}
int main(){
	for (int i=1;i<=9;i++){
		for (int j=1;j<=9;j++){
			cin>>a[i][j];
			if (a[i][j]!=0){
				h[i][a[i][j]]=1;
				l[j][a[i][j]]=1;
				g[(i-1)/3+1][(j-1)/3+1][a[i][j]]=1;
			}
		}
	}
	dfs(1,1);
	return 0;
}

这道题会了的话我们来看一个有一点变形的

Description

题目背景

数独是指满足如下条件的 9×9矩阵:

  • 每一行、每一列都包含从 1 至 9 不重不漏的数字;
  • 将其划分为 9 个 3×3 的小矩阵,每个小矩阵也都包含从 1 至 9 不重不漏的数字。

题目描述

给出一个 9×9 的矩阵,里面填了一些 1 至 9 之间的整数,将其补全为一个完整的数独并输出。未填数的格子以 0 表示。

输入格式

从标准输入读入数据。

输入共 9 行,每行包含 9 个整数 aij​(0≤aij​≤9),整数之间不含空格,代表待补全的数独。

输出格式

输出到标准输出。

如果数独有解,输出共 9 行,每行包含 9 个整数 aij​(1≤aij​≤9),整数之间不含空格,代表填好后的数独。

如果有多于一个解,任意输出一个解即可。

如果数独无解,输出 0 。

这道题其实就只需要再判断完之后输出一个0就可以了,非常的easy

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

int h[10][10],l[10][10],a[10][10],ans[10][10],g[5][5][10],cmp;

void dfs(int x,int y){
	int flag=1;
	
	if (cmp==1)return;
	if (x==10&&y==1){
		for (int i=1;i<=9;i++){
			for (int j=1;j<=9;j++){
				cout<<ans[i][j];
			}
			cout<<endl;
		}
		cmp=1;
		exit(0);
	}
	
	if (a[x][y]!=0){
		ans[x][y]=a[x][y];
		if (y==9){
			dfs(x+1,1);
		}else {
			dfs(x,y+1);
		}
		return;
	}else {
		for (int i=1;i<=9;i++){
			if (h[x][i]==0&&l[y][i]==0&&g[(x-1)/3+1][(y-1)/3+1][i]==0){
				flag=0;
				//
				h[x][i]=1;
				l[y][i]=1;
				g[(x-1)/3+1][(y-1)/3+1][i]=1;
				ans[x][y]=i;
				//
				if (y==9){
					dfs(x+1,1);
				}else {
					dfs(x,y+1);
				}
				//
				h[x][i]=0;
				l[y][i]=0;
				g[(x-1)/3+1][(y-1)/3+1][i]=0;
			}
		}
	}
	return;
}
int main(){
	string s;
	for (int i=1;i<=9;i++){
		cin>>s;
		for (int j=1;j<=9;j++){
			a[i][j]=s[j-1]-'0';
			if (a[i][j]!=0){
				h[i][a[i][j]]=1;
				l[j][a[i][j]]=1;
				g[(i-1)/3+1][(j-1)/3+1][a[i][j]]=1;
			}
		} 
	}
	dfs(1,1);
    cout<<0;
	return 0;
}

最后我们看一道[NOIP2009 提高组] 靶形数独 - 洛谷——提高+/省选-

题目背景

此为远古题,不保证存在可以通过任意符合要求的输入数据的程序

题目描述

小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低。但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博士拿出了他最近发明的“靶形数独”,作为这两个孩子比试的题目。

靶形数独的方格同普通数独一样,在 9 格宽且 9 格高的大九宫格中有 9 个 3 格宽且 3 格高的小九宫格(用粗黑色线隔开的)。在这个大九宫格中,有一些数字是已知的,根据这些数字,利用逻辑推理,在其他的空格上填入 1 到 9 的数字。每个数字在每个小九宫格内不能重复出现,每个数字在每行、每列也不能重复出现。但靶形数独有一点和普通数独不同,即每一个方格都有一个分值,而且如同一个靶子一样,离中心越近则分值越高。(如图)

上图具体的分值分布是:最里面一格(黄色区域)为 10 分,黄色区域外面的一圈(红色区域)每个格子为 9 分,再外面一圈(蓝色区域)每个格子为 8 分,蓝色区域外面一圈(棕色区域)每个格子为 7 分,最外面一圈(白色区域)每个格子为 6 分,如上图所示。比赛的要求是:每个人必须完成一个给定的数独(每个给定数独可能有不同的填法),而且要争取更高的总分数。而这个总分数即每个方格上的分值和完成这个数独时填在相应格上的数字的乘积的总和

总分数即每个方格上的分值和完成这个数独时填在相应格上的数字的乘积的总和。如图,在以下的这个已经填完数字的靶形数独游戏中,总分数为 2829。游戏规定,将以总分数的高低决出胜负。

由于求胜心切,小城找到了善于编程的你,让你帮他求出,对于给定的靶形数独,能够得到的最高分数。

输入格式

一共 9 行。每行 9 个整数(每个数都在0∼9 的范围内),表示一个尚未填满的数独方格,未填的空格用“0”表示。每两个数字之间用一个空格隔开。

输出格式

输出共 1 行。输出可以得到的靶形数独的最高分数。如果这个数独无解,则输出整数−1。

首先这道题如果用上面的方法来写的话,只能拿60分,其实这个分数在赛场上是比较可以了的,但是嘛,我们是学习,自然要弄懂才行,所以我们来具体分析分析:

首先我们知道在填数独的时候,一般情况下会去填这一行或这一列已经有比较多的数字了的地方,那么我们可不可以利用这个方法,找到每一行所剩下的位置有几个,然后排一个序,从小往大的去找呢?这个思路就非常非常的好了,可以拿整整100分!

ACcode

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

inline int read(){
	int x=0;
	char ch=0;
	while (ch<'0'||ch>'9')ch=getchar();
	while (ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
	return x;
}//用了一下快读,可以提速
int h[10][10],l[10][10],a[10][10],ans[10][10],g[5][5][10],maxn=-1,cnt=1;

int fen[10][10]={{0,0,0,0,0,0,0,0,0,0},{0,6,6,6,6,6,6,6,6,6},{0,6,7,7,7,7,7,7,7,6},{0,6,7,8,8,8,8,8,7,6},{0,6,7,8,9,9,9,8,7,6},{0,6,7,8,9,10,9,8,7,6},{0,6,7,8,9,9,9,8,7,6},{0,6,7,8,8,8,8,8,7,6},{0,6,7,7,7,7,7,7,7,6},{0,6,6,6,6,6,6,6,6,6}};//手动打表

struct f{
    int num=9;
    int hang;
}sx[10];

bool cmp(f a1,f a2){
    return a1.num<a2.num;
}

void dfs(int x,int y){
	if (cnt==10){
		int cnt=0;
		for (int i=1;i<=9;i++){
			for (int j=1;j<=9;j++){
				cnt+=ans[i][j]*fen[i][j];
			}
		}
		maxn=max(maxn,cnt);
		return;
	}
	
	if (a[x][y]!=0){
		ans[x][y]=a[x][y];
		if (y==9){
            cnt++;
			dfs(sx[cnt].hang,1);
            cnt--;
		}else {
			dfs(x,y+1);
		}
		return;
	}else {
		for (int i=1;i<=9;i++){
			if (h[x][i]==0&&l[y][i]==0&&g[(x-1)/3+1][(y-1)/3+1][i]==0){
				h[x][i]=1;
				l[y][i]=1;
				g[(x-1)/3+1][(y-1)/3+1][i]=1;
				ans[x][y]=i;
				//
				if (y==9){
                    cnt++;
					dfs(sx[cnt].hang,1);
                    cnt--;//这个也要回溯,当初我就是在这里卡了好久
				}else {
					dfs(x,y+1);
				}
				//
				h[x][i]=0;
				l[y][i]=0;
				g[(x-1)/3+1][(y-1)/3+1][i]=0;
			}
		}
	}

	return;
}

int main(){
	for (int i=1;i<=9;i++){
        sx[i].hang=i;//存下行的位置
		for (int j=1;j<=9;j++){
			a[i][j]=read();
			if (a[i][j]!=0){
				h[i][a[i][j]]=1;
				l[j][a[i][j]]=1;
				g[(i-1)/3+1][(j-1)/3+1][a[i][j]]=1;
                sx[i].num--;
			}
		}
	}
    sort(sx+1,sx+10,cmp);
	dfs(sx[cnt].hang,1);
	cout<<maxn;
	return 0;
}

 

  看了这么久,作者也写了这么久,能不能点一个赞,在收藏一下呢?最好的话在点个关注吧

谢谢啦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/502238.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

3-zookeeper之ZAB协议

Zookeeper ZAB协议 概述 ZAB(Zookeeper Automic Broadcast)是一套专门为Zookeeper设计的用于进行原子广播和崩溃恢复的协议ZAB协议主要包含了两个功能 原子广播&#xff1a;保证数据一致性崩溃恢复&#xff1a;保证集群的高可用 ZAB协议本身是基于2PC算法来进行的设计&#…

【js刷题:数据结构数组篇之有序数组的平方】

有序数组的平方 一、题目二、解题方法1、暴力解法2、双指针思路代码 一、题目 给你一个按 非递减顺序 排序的整数数组 nums&#xff0c;返回 每个数字的平方 组成的新数组&#xff0c;要求也按 非递减顺序 排序。 二、解题方法 1、暴力解法 class Solution {sortedSquares(…

数据结构与算法 双链表有序排列运算与循环单链表基本运算

一、实验内容 1.有一个带头结点的双链表L&#xff08;至少有一个数据结点&#xff09;&#xff0c;设计一个算法使其元素递增有序排列。 2. 编写一个程序clinklist.cpp,实现循环单链表的各种基本运算和整体建表算法&#xff08;假设循环单链表的元素类型ElemType为char&#…

OSCP靶场--Zipper

OSCP靶场–Zipper 考点(php zip:// rce[文件上传] CVE-2021-4034提权7z 通配符提权) 1.nmap扫描 ┌──(root㉿kali)-[~/Desktop] └─# nmap 192.168.249.229 -sV -sC -Pn --min-rate 2500 Starting Nmap 7.92 ( https://nmap.org ) at 2024-03-29 07:40 EDT …

11-设计模式:Go常用设计模式概述

设计模式是啥呢&#xff1f;简单来说&#xff0c;就是将软件开发中需要重复性解决的编码场景&#xff0c;按最佳实践的方式抽象成一个模型&#xff0c;模型描述的解决方法就是设计模式。使用设计模式&#xff0c;可以使代码更易于理解&#xff0c;保证代码的重用性和可靠性。 …

RIP环境下的MGRE 综合实验

实验题目及要求&#xff1a; 1.R5为ISP&#xff0c;只能进行IP地址配置&#xff0c;其所有地址均配为公有IP地址 2.R1和R5间使用PPP的PAP认证&#xff0c;R5为主认证方; R2于R5之间使用PPP的chap认证&#xff0c;R5为主认证方&#xff1b; R3于R5之间使用HDLC封装。 3.R1/…

基于javaweb宠物领养平台管理系统设计和实现

基于javaweb宠物领养平台管理系统设计和实现 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言 文末获取源码联…

媒体偏见从何而来?--- 美国MRC(媒体评级委员会)为何而生?

每天当我们打开淘宝&#xff0c;京东&#xff0c;步入超市&#xff0c;逛街或者逛展会&#xff0c;各种广告铺天盖地而来。从原来的平面广告&#xff0c;到多媒体广告&#xff0c;到今天融合AR和VR技术的数字广告&#xff0c;还有元宇宙虚拟世界&#xff0c;还有大模型加持的智…

SpringBoot使用Redis

1.Spring是如何集成Redis的&#xff1f; Spring Data Redis 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId&…

第十四届蓝桥杯JavaA组省赛真题 - 棋盘

解题思路&#xff1a; 暴力 棋盘类题目取反操作&#xff1a; f[a][b]^1; 或者f[a][b] 1 - f[a][b]; import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scan new Scanner(System.in);int n scan.nextInt();int m scan.nex…

MyEclipse10配置Tomcat7+Web项目发布

配置时&#xff0c;MyEclipse→Preference&#xff0c;在左边栏目中选择MyEclipse——Servers——Tomcat——Tomcat7.x&#xff0c;如下&#xff1a; 把Tomcat服务器设为可用&#xff0c;选择Tomcat的路径&#xff08;选择Tomcat路径的时候一定要选对&#xff0c;不要选Tomcat下…

STM32使用U盘进行固件更新

前面提过串口IAP升级可以方便的进行不拆机固件更新 STM32串口IAP-CSDN博客文章浏览阅读577次,点赞20次,收藏6次。那么有哪些便捷的升级方式呢,其实有很多,比较常见的比如手机软件更新,很典型的远程升级案例。前面说过“修改STM32链接脚本可以修改程序写入闪存的起始地址”…

位置_分布式处理和数据的MVA考虑——可持续架构(七)

前言 理解分布式进程和数据的影响&#xff0c;可以使团队尚在未具备处理分布式能力的时候&#xff0c;做出更好的MVA决策。云计算并不能消除分布式问题&#xff0c;反而它可能会使问题更难解决&#xff0c;因为它隐藏了底层基础设施。改变数据位置可能会对应用程序逻辑产生微妙…

基于单片机的温度控制器系统仿真设计

**单片机设计介绍&#xff0c;基于单片机的温度控制器系统仿真设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的温度控制器系统仿真设计概要主要包括以下几个关键方面&#xff1a;硬件设计、软件设计、系统仿真与…

颜值测评打分微信小程序AI智能颜值测评小程序搭建流量主收益

功能简介&#xff1a; 1.该小程序是AI智能颜值测评 2.可配合流量主推广&#xff0c;广告变现 3.后台含有区间关键词&#xff0c;颜值分析管理可用于公众号吸粉 (保存海报上的二维码换成公众号二维码) 4.(美容院&#xff0c;整形机构活动&#xff0c;颜值评分X分以上可到店获…

安卓手机ip地址怎么切换?简单几步轻松实现

在移动互联网时代&#xff0c;安卓手机作为我们日常生活中不可或缺的一部分&#xff0c;扮演着越来越重要的角色。而在网络世界中&#xff0c;IP地址则是每个设备的标识&#xff0c;它决定了设备在网络中的位置与身份。然而&#xff0c;有时我们可能出于隐私保护、网络测试或其…

PTA L2-040 哲哲打游戏

哲哲是一位硬核游戏玩家。最近一款名叫《达诺达诺》的新游戏刚刚上市&#xff0c;哲哲自然要快速攻略游戏&#xff0c;守护硬核游戏玩家的一切&#xff01; 为简化模型&#xff0c;我们不妨假设游戏有 N 个剧情点&#xff0c;通过游戏里不同的操作或选择可以从某个剧情点去往另…

Jmeter —— 接口之间关联调用(获取上一个接口的返回值作为下一个接口的请求参数)

正则表达式&#xff1a; 具体如何操作&#xff1a; 1. 草稿保存&#xff0c; 此请求的响应数据的id 为发布总结的请求参数draft_id 2. 草稿保存的响应数据 3.在草稿保存的请求中&#xff0c;添加后置处理器- 正则表达式提取器&#xff0c; 提取响应数据的id信息 4. 发布总结请…

Linux+ARM 简单环境检测---软件部分

1、前言 这个是我学习linuxARM的在做的第一个软硬件结合项目&#xff0c;以往的类似这种整体类项目还是光单片机的时候&#xff0c;linux软件部分学习了差不多快一年了&#xff0c;因为各种事情耽搁&#xff0c;这个项目一直没有静下心来完成&#xff0c;不过终于哈哈哈哈搞完了…

【Java】:封装和包

目录 1.封装的概念 2.访问限定符号 3.封装扩展之包 3.1包的概念 3.2导入包中的类 3.3自定义包 3.4常见的包 1.封装的概念 面向对象程序三大特性&#xff1a;封装、继承、多态。何为封装&#xff1f;简单来说就是套壳屏蔽细节。 比如&#xff1a;对于电脑这样一个复杂的…