当前位置: 首页 > news >正文

蓝桥云客---九宫幻方

1.九宫幻方 - 蓝桥云课

九宫幻方

题目描述

小明最近在教邻居家的小朋友小学奥数,而最近正好讲述到了三阶幻方这个部分,三阶幻方指的是将1~9不重复的填入一个3 * 3的矩阵当中,使得每一行、每一列和每一条对角线的和都是相同的。

三阶幻方又被称作九宫格,在小学奥数里有一句非常有名的口诀:“二四为肩,六八为足,左三右七,戴九履一,五居其中”,通过这样的一句口诀就能够非常完美的构造出一个九宫格来。

492
357
816

有意思的是,所有的三阶幻方,都可以通过这样一个九宫格进行若干镜像和旋转操作之后得到。现在小明准备将一个三阶幻方(不一定是上图中的那个)中的一些数抹掉,交给邻居家的小朋友来进行还原,并且希望她能够判断出究竟是不是只有一个解。

而你呢,也被小明交付了同样的任务,但是不同的是,你需要写一个程序。

输入描述

输入仅包含单组测试数据。

每组测试数据为一个3 * 3的矩阵,其中为0的部分表示被小明抹去的部分。

给出的矩阵至少能还原出一组可行的三阶幻方。

输出描述

如果仅能还原出一组可行的三阶幻方,则将其输出,否则输出"Too Many"(不包含引号)。

输入输出样例

​示例​

​输入​

0 7 2
0 5 0
0 3 0

​输出​

6 7 2
1 5 9
8 3 4

思路:

题目要求,只有一个解那么久输出这个解,如果多个解就输出too many。所以我们需要用一个数组储存第一个解。(题目说了输入数据会有解的)。

1.因为我们要填空,但是这个二维数组的填空有点麻烦,所以我们可以将每一个需要填空的位置记录在一个一维数组里面,这样就比较好爆搜了。

2.利用桶思维保证每一个数字只出现一次

3.check函数检查


代码如下:

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

struct Node{
 int x, y; 
 }pos[10];//储存位置的数组 
int a[4][4], res[4][4];
bool used[10]; 
int cnt, ans;
bool check()
{
	for(int i = 1 ; i <= 3 ; i++)//判断行和列 
	{
		int s_row = a[i][1] + a[i][2] + a[i][3];
		int s_rank = a[1][i] + a[2][i] + a[3][i];
		if(s_row != 15 || s_rank != 15)
		return false;	
	}
	int s_pd = a[1][1] + a[2][2] + a[3][3];
	int s_nd = a[1][3] + a[2][2] + a[3][1];
	if(s_pd != 15 || s_nd != 15)
	return false;
	
	return true; 
}
void dfs(int step) 
{
    if (ans > 1) 
	return; // 发现多解立即终止
    
    if (step > cnt) 
	{
        if (check()) 
		{
            ans++;
            if (ans == 1) // 仅保存第一个解
           	{
           		for(int i = 1 ; i <= 3 ; i++)
			   {
					for(int j = 1 ; j <= 3 ; j++)
					{
						res[i][j] = a[i][j];				
				    }		   	
			   }	
			}
        }
        return;
    }
    int x = pos[step].x, y = pos[step].y;//取出坐标 
    for (int i = 1; i <= 9; i++) 
	{
        if (!used[i]) 
		{
            used[i] = true;
            a[x][y] = i;
            dfs(step + 1);
            used[i] = false;
            a[x][y] = 0; // 回溯
        }
    }
}
int main() 
{
    for (int i = 1; i <= 3; i++) 
	{
        for (int j = 1; j <= 3; j++) 
		{
            cin >> a[i][j];
            if (a[i][j] == 0) 
			{
				++cnt;
                pos[cnt].x = i; // 从1开始记录待填位置
                pos[cnt].y = j;
            } 
			else 
			{
                used[a[i][j]] = true; // 标记已用数字
            }
        }
    }
    dfs(1);
    if (ans == 1) 
	{
        for (int i = 1; i <= 3; i++) 
		{
            for (int j = 1; j <= 3; j++) 
			{
                cout << res[i][j] << " ";
            }
            cout << endl;
        }
    } 
	else 
	{
        cout << "Too Many";
    }
    return 0;
}

思路:

二维数组写法,直接模拟x,y负责填数字即可

代码:

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

struct Node{
 int x, y; 
 }pos[10];//储存位置的数组 
int a[4][4], res[4][4];
bool used[10]; 
int cnt, ans;
bool check()
{
	for(int i = 1 ; i <= 3 ; i++)//判断行和列 
	{
		int s_row = a[i][1] + a[i][2] + a[i][3];
		int s_rank = a[1][i] + a[2][i] + a[3][i];
		if(s_row != 15 || s_rank != 15)
		return false;	
	}
	int s_pd = a[1][1] + a[2][2] + a[3][3];
	int s_nd = a[1][3] + a[2][2] + a[3][1];//对角线 
	if(s_pd != 15 || s_nd != 15)
	return false;
	
	return true; 
}
void dfs(int x,int y) 
{
    if (ans > 1) 
	return; // 发现多解立即终止
 	if(y > 3)
	{
		x++;
		y = 1;
	}   
	
    if (x > 3) 
	{
        if (check()) 
		{
            ans++;
            if (ans == 1) // 仅保存第一个解
           	{
           		for(int i = 1 ; i <= 3 ; i++)
			   {
					for(int j = 1 ; j <= 3 ; j++)
					{
						res[i][j] = a[i][j];				
				    }		   	
			   }	
			}
        }
        return;
    }
    if(a[x][y] == 0)
    {
    	for(int i = 1 ; i <= 9 ; i++)
    	{
	        if (!used[i]) 
			{
	            used[i] = true;
	            a[x][y] = i;
	            dfs(x,y+1);
	            used[i] = false;
	            a[x][y] = 0; // 回溯
	       	}
		}
	}
	else
	{
		dfs(x,y+1);
	}

}
int main() 
{
    for (int i = 1; i <= 3; i++) 
	{
        for (int j = 1; j <= 3; j++) 
		{
            cin >> a[i][j];
            if(a[i][j] > 0)
            used[a[i][j]] = true; 
        }
    }
    dfs(1,1);
    if (ans == 1) 
	{
        for (int i = 1; i <= 3; i++) 
		{
            for (int j = 1; j <= 3; j++) 
			{
                cout << res[i][j] << " ";
            }
            cout << endl;
        }
    } 
	else 
	{
        cout << "Too Many";
    }
    return 0;
}


文章转载自:
http://tetragon.riewr.cn
http://petrograd.riewr.cn
http://splenii.riewr.cn
http://clearing.riewr.cn
http://quercitron.riewr.cn
http://ideamonger.riewr.cn
http://uncountable.riewr.cn
http://twirl.riewr.cn
http://midweek.riewr.cn
http://coccidiosis.riewr.cn
http://diazomethane.riewr.cn
http://detrited.riewr.cn
http://community.riewr.cn
http://alkene.riewr.cn
http://kowtow.riewr.cn
http://bumblebee.riewr.cn
http://eisa.riewr.cn
http://liquidation.riewr.cn
http://uprose.riewr.cn
http://bursiculate.riewr.cn
http://geniculum.riewr.cn
http://explainable.riewr.cn
http://stet.riewr.cn
http://qmg.riewr.cn
http://absolutely.riewr.cn
http://blotch.riewr.cn
http://puzzlist.riewr.cn
http://superglacial.riewr.cn
http://colchicum.riewr.cn
http://graptolite.riewr.cn
http://www.dtcms.com/a/111450.html

相关文章:

  • ngx_ssl_init
  • 【2-7】脉码调制
  • Apache httpclient okhttp(2)
  • 【winodws】夜神模拟器虚拟机启动失败,请进行修复。关闭hyper-v
  • CSS Id 和 Class 选择器学习笔记
  • 【嵌入式-stm32电位器控制LED亮灭以及编码器控制LED亮灭】
  • 标准库文档
  • 基于时间卷积网络TCN实现电力负荷多变量时序预测(PyTorch版)
  • 如何确保MQ消息队列不丢失:Java实现与流程分析
  • ubuntu20.04升级成ubuntu22.04
  • JavaScript BOM核心对象、本地存储
  • Linux学习笔记7:关于i.MX6ULL主频与时钟配置原理详解
  • Cribl 导入文件来检查pipeline 的设定规则(eval 等)
  • NO.64十六届蓝桥杯备战|基础算法-简单贪心|货仓选址|最大子段和|纪念品分组|排座椅|矩阵消除(C++)
  • 【如何设置Element UI的Dialog弹窗允许点击背景内容】
  • Linux系统之wc命令的基本使用
  • 华为高斯(GaussDB) 集中式数据库 的开发技术手册,涵盖核心功能、开发流程、优化技巧及常见问题解决方案
  • 深度学习数据集划分比例多少合适
  • Linux make 检查依赖文件更新的原理
  • PyTorch张量
  • Opencv计算机视觉编程攻略-第九节 检测兴趣点
  • Linux systemd 服务全面详解
  • SQL语句(三)—— DQL
  • 详解AI采集框架Crawl4AI,打造智能网络爬虫
  • poetry安装
  • Transformer+BO-SVM时间序列预测(Matlab)
  • 第十五届蓝桥杯大赛软件赛省赛Python 大学 C 组:5.回文数组
  • 系统分析师-前6章总结
  • STM32单片机入门学习——第14节: [6-2] 定时器定时中断定时器外部时钟
  • PGSQL 对象创建函数生成工具