‘壹’ 将1到9填在九宫格内 怎么样使横行都是偶数
首先满足条件的九宫格填充方法并不存在。
因为九宫格填充要求每行、每列两个对角线上的三数之和都等于15,如果任意一横行都是偶数,那么所在行的数字和必不可能等于奇数。
那么遍历所有九宫格填充方法,只能得到4种解,同样找不到符合条件的解。
1、此解是九宫格解,确不满足题目条件
(1)九宫格元素遍历问题解决方法扩展阅读:
九宫格排列是数学里的三阶幻方。幻方是一种将数字安排在正方形格子中,使每行、列和对角线上的数字和都相等的方法。
幻方又包括:完全幻方、乘幻方、高次幻方等。
完全幻方,指一个幻方行、列、主对角线及泛对角线各数之和均相等 [1] 。
乘幻方,指一个幻方行列、对角线各数乘积相等。
高次幻方,n阶幻方是由前n^2(n的2次方)个自然数组成的一个n阶方阵,其各行、各列及两条对角线所含的n个数的和相等。
‘贰’ “样式遍历”,公考图形推理当中经常用到这个词汇,但是不太理解,求高人指点迷津。
送你一句华图老师对样式遍历的概述:
样式遍历:不改变样式的种类,只改变样式的顺序。
样式遍历多出现在于九宫格里,先看样式遍历再看加减同异。
最后附赠两道例题
‘叁’ 2017年联考:图形推理九宫格出题形式技巧点拨
按以往的考请看,联考中图形推理考查规律推理与重构推理两大类,规律推理包括:数量类规律、样式类规律、位置类规律等,出题形式比较灵活,有一条式、两段式、九宫格、分组分类。一般在九宫格的出题形式下,题目较难,考查规律的方式也较多。因此在这种出题形式下,应该引起大家的重视。而我们观察九宫格可以从以下几种形式去观察。
1.九宫格横行规律。在这种出题形式下,解题方法为:寻找第一行的规律,用第二行验证规律,在第三行应用规律。例如:
【例1】从所给四个选项中,选择最合适的一个填入问号处,使之呈现一定的规律性:
【答案】B
【解析】图形组成相似,我们可以考虑样式类规律,样式类包括遍历和运算,而此题的规律为米字型两端叠加求中间,选B。
‘肆’ 九宫格数独游戏最简单最实用的解法
基本解法分为两类思路:
排除法
就是利用1~9的数字在每一行、每一列、每一个九宫格都只能出现一次的规则进行解题的方法。基础摒除法可以分为行摒除、列摒除、九宫格摒除。
唯一法
当某行已填数字的宫格达到8个,那么该行剩余宫格能填的数字就只剩下那个还没出现过的数字了,成为行唯一解。
‘伍’ 九宫格怎么破解!
1.联除法.
在并排的三个九宫格中的两排寻找相同数字,再利用九宫格得出另一排中该数字位置,该方法适用于中高级数独.
2.巡格法
找出在每个九宫格中出现频率较高的数字,得出该数字在其余九宫格内位置,该方法应用于方法一之后.
3.排它法
这个方法是解决问题的关键,易被常人所忽略.在各行列或九宫格中观察,若有个位置其它数字都不能填,就填余下的数字
4.待定法
此方法不常用却很有效.暂时确定某个数字在某个区域,再利用其来进行排除
5.行列法
此方法用于收官阶段,利用先从行列突破来提高解题效率.
6.假设法
作为一名高手,我不提倡这种方法.即在某个位置随机的填上一个数字,再进行推演,并有可能最终产生矛盾而否定结论.
7.频率法
这种方法相比于上一种方法更能提高效率.在某一行列或九宫格列举出所有情况,再选择某位置中出现频率高的数字
‘陆’ 九宫格拼图·求此问题解法~~思路~代码都可~~就是关于其还原算法的·急~在线等~多谢哈
http://www.cublog.cn/u/8780/showart.php?id=163291
在一个3×3的九宫中有1-8这8个数及一个空格随机的摆放在其中的格子里,如图1-1所示。现在要求实现这个问题:将其调整为如图1-1右图所示的形式。调整的规则是:每次只能将与空格(上、下、或左、右)相邻的一个数字平移到空格中。试编程实现这一问题的求解。
(图1-1)
二、题目分析:
这是人工智能中的经典难题之一,问题是在3×3方格棋盘中,放8格数,剩下的没有放到的为空,每次移动只能是和相邻的空格交换数。程序自动产生问题的初始状态,通过一系列交换动作将其转换成目标排列(如下图1-2到图1-3的转换)。
(图1-2) (图1-3)
该问题中,程序产生的随机排列转换成目标共有两种可能,而且这两种不可能同时成立,也就是奇数排列和偶数排列。可以把一个随机排列的数组从左到右从上到下用一个一维数组表示,如上图1-2我们就可以表示成{8,7,1,5,2,6,3,4,0}其中0代表空格。
在这个数组中我们首先计算它能够重排列出来的结果,公式就是:
∑(F(X))=Y,其中F(X)
是一个数前面比这个数小的数的个数,Y为奇数和偶数时各有一种解法。(八数码问题是否有解的判定 )
上面的数组可以解出它的结果。
F(8)=0;
F(7)=0;
F(1)=0;
F(5)=1;
F(2)=1;
F(6)=3;
F(3)=2;
F(4)=3;
Y=0+0+0+1+1+3+2+3=10
Y=10是偶数,所以其重排列就是如图1-3的结果,如果加起来的结果是奇数重排的结果就是如图1-1最右边的排法。
三、算法分析
求解方法就是交换空格(0)位置,直至到达目标位置为止。图形表示就是:
(图3-1)
要想得到最优的就需要使用广度优先搜索,九宫的所以排列有9!种,也就是362880种排法,数据量是非常大的,使用广度搜索,需要记住每一个结点的排列形式,要是用数组记录的话会占用很多的内存,可以把数据进行适当的压缩。使用DWORD形式保存,压缩形式是每个数字用3位表示,这样就是3×9=27个字节,由于8的二进制表示形式1000,不能用3位表示,使用了一个小技巧就是将8表示为000,然后用多出来的5个字表示8所在的位置,就可以用DWORD表示了。用移位和或操作将数据逐个移入,比乘法速度要快点。定义了几个结果来存储遍历到了结果和搜索完成后保存最优路径。
类结构如下:
class CNineGird
{
public:
struct PlaceList
{
DWORD Place;
PlaceList* Left;
PlaceList* Right;
};
struct Scanbuf
{
DWORD Place;
int ScanID;
};
struct PathList
{
unsigned char Path[9];
};
private:
PlaceList *m_pPlaceList;
Scanbuf *m_pScanbuf;
RECT m_rResetButton;
RECT m_rAutoButton;
public:
int m_iPathsize;
clock_t m_iTime;
UINT m_iStepCount;
unsigned char m_iTargetChess[9];
unsigned char m_iChess[9];
HWND m_hClientWin;
PathList *m_pPathList;
bool m_bAutoRun;
private:
inline bool AddTree(DWORD place , PlaceList*& parent);
void FreeTree(PlaceList*& parent);
inline void ArrayToDword(unsigned char *array , DWORD & data);
inline void DwordToArray(DWORD data , unsigned char *array);
inline bool MoveChess(unsigned char *array , int way);
bool EstimateUncoil(unsigned char *array);
void GetPath(UINT depth);
public:
void MoveChess(int way);
bool ComputeFeel();
void ActiveShaw(HWND hView);
void DrawGird(HDC hDC , RECT clientrect);
void DrawChess(HDC hDC , RECT clientrect);
void Reset();
void OnButton(POINT pnt , HWND hView);
public:
CNineGird();
~CNineGird();
};
计算随机随机数组使用了vector模板用random_shuffle(,)函数来打乱数组数据,并计算目标结果是什么。代码:
void CNineGird::Reset()
{
if(m_bAutoRun) return;
vector vs;
int i;
for (i = 1 ; i < 9 ; i ++)
vs.push_back(i);
vs.push_back(0);
random_shuffle(vs.begin(), vs.end());
random_shuffle(vs.begin(), vs.end());
for ( i = 0 ; i < 9 ; i ++)
{
m_iChess[i] = vs[i];
}
if (!EstimateUncoil(m_iChess))
{
unsigned char array[9] = {1,2,3,8,0,4,7,6,5};
memcpy(m_iTargetChess , array , 9);
}
else
{
unsigned char array[9] = {1,2,3,4,5,6,7,8,0};
memcpy(m_iTargetChess , array , 9);
}
m_iStepCount = 0;
}
数据压缩函数实现:
inline void CNineGird::ArrayToDword(unsigned char *array , DWORD& data)
{
unsigned char night = 0;
for ( int i = 0 ; i < 9 ; i ++)
{
if (array[i] == 8)
{
night = (unsigned char)i;
break;
}
}
array[night] = 0;
data = 0;
data = (DWORD)((DWORD)array[0] << 29 | (DWORD)array[1] << 26 |
(DWORD)array[2] << 23 | (DWORD)array[3] << 20 |
(DWORD)array[4] << 17 | (DWORD)array[5] << 14 |
(DWORD)array[6] << 11 | (DWORD)array[7] << 8 |
(DWORD)array[8] << 5 | night);
array[night] = 8;
}
解压缩时跟压缩正好相反,解压代码:
inline void CNineGird::DwordToArray(DWORD data , unsigned char *array)
{
unsigned char chtem;
for ( int i = 0 ; i < 9 ; i ++)
{
chtem = (unsigned char)(data >> (32 - (i + 1) * 3) & 0x00000007);
array[i] = chtem;
}
chtem = (unsigned char)(data & 0x0000001F);
array[chtem] = 8;
}
由于可扩展的数据量非常的大,加上在保存的时候使用的是DWORD类型,将每一步数据都记录在一个排序二叉树中,按从小到大从左到有的排列,搜索的时候跟每次搜索将近万次的形式比较快几乎是N次方倍,把几个在循环中用到的函数声明为内联函数,并在插入的时候同时搜索插入的数据会不会在树中有重复来加快总体速度。二叉树插入代码:
inline bool CNineGird::AddTree(DWORD place , PlaceList*& parent)
{
if (parent == NULL)
{
parent = new PlaceList();
parent->Left = parent->Right = NULL;
parent->Place = place;
return true;
}
if (parent->Place == place)
return false;
if (parent->Place > place)
{
return AddTree(place , parent->Right);
}
return AddTree(place , parent->Left);
}
计算结果是奇数排列还是偶数排列的代码:
bool CNineGird::EstimateUncoil(unsigned char *array)
{
int sun = 0;
for ( int i = 0 ; i < 8 ; i ++)
{
for ( int j = 0 ; j < 9 ; j ++)
{
if (array[j] != 0)
{
if (array[j] == i +1 )
break;
if (array[j] < i + 1)
sun++;
}
}
}
if (sun % 2 == 0)
return true;
else
return false;
}
移动到空格位的代码比较简单,只要计算是否会移动到框外面就可以了,并在移动的时候顺便计算一下是不是已经是目标结果,这是用来给用户手工移动是给与提示用的,代码:
inline bool CNineGird::MoveChess(unsigned char *array , int way)
{
int zero , chang;
bool moveok = false;
for ( zero = 0 ; zero < 9 ; zero ++)
{
if (array[zero] == 0)
break;
}
POINT pnt;
pnt.x = zero % 3;
pnt.y = int(zero / 3);
switch(way)
{
case 0 : //up
if (pnt.y + 1 < 3)
{
chang = (pnt.y + 1) * 3 + pnt.x ;
array[zero] = array[chang];
array[chang] = 0;
moveok = true;
}
break;
case 1 : //down
if (pnt.y - 1 > -1)
{
chang = (pnt.y - 1) * 3 + pnt.x ;
array[zero] = array[chang];
array[chang] = 0;
moveok = true;
}
break;
case 2 : //left
if (pnt.x + 1 < 3)
{
chang = pnt.y * 3 + pnt.x + 1;
array[zero] = array[chang];
array[chang] = 0;
moveok = true;
}
break;
case 3 : //right
if (pnt.x - 1 > -1)
{
chang = pnt.y * 3 + pnt.x - 1;
array[zero] = array[chang];
array[chang] = 0;
moveok = true;
}
break;
}
if (moveok && !m_bAutoRun)
{
m_iStepCount ++ ;
DWORD temp1 ,temp2;
ArrayToDword(array , temp1);
ArrayToDword(m_iTargetChess , temp2);
if (temp1 == temp2)
{
MessageBox(NULL , "你真聪明这么快就搞定了!" , "^_^" , 0);
}
}
return moveok;
}
在进行广度搜索时候,将父结点所在的数组索引记录在子结点中了,所以得到目标排列的时候,只要从子结点逆向搜索就可以得到最优搜索路径了。用变量m_iPathsize来记录总步数,具体函数代码:
void CNineGird::GetPath(UINT depth)
{
int now = 0 , maxpos = 100 ;
UINT parentid;
if (m_pPathList != NULL)
{
delete[] m_pPathList;
}
m_pPathList = new PathList[maxpos];
parentid = m_pScanbuf[depth].ScanID;
DwordToArray(m_pScanbuf[depth].Place , m_pPathList[++now].Path);
while(parentid != -1)
{
if (now == maxpos)
{
maxpos += 10;
PathList * temlist = new PathList[maxpos];
memcpy(temlist , m_pPathList , sizeof(PathList) * (maxpos - 10));
delete[] m_pPathList;
m_pPathList = temlist;
}
DwordToArray(m_pScanbuf[parentid].Place , m_pPathList[++now].Path);
parentid = m_pScanbuf[parentid].ScanID;
}
m_iPathsize = now;
}
动态排列的演示函数最简单了,为了让主窗体有及时刷新的机会,启动了一个线程在需要主窗体刷新的时候,用Slee(UINT)函数来暂停一下线程就可以了。代码:
unsigned __stdcall MoveChessThread(LPVOID pParam)
{
CNineGird * pGird = (CNineGird *)pParam;
RECT rect;
pGird->m_iStepCount = 0;
::GetClientRect(pGird->m_hClientWin , &rect);
for ( int i = pGird->m_iPathsize ; i > 0 ; i --)
{
memcpy(pGird->m_iChess , pGird->m_pPathList[i].Path , 9);
pGird->m_iStepCount ++;
InvalidateRect( pGird->m_hClientWin , &rect , false);
Sleep(300);
}
char msg[100];
sprintf(msg , "^_^ ! 搞定了!\r\n计算步骤用时%d毫秒" , pGird->m_iTime);
MessageBox(NULL , msg , "~_~" , 0);
pGird->m_bAutoRun = false;
return 0L;
}
最后介绍一下搜索函数的原理,首先得到源数组,将其转换成DWORD型,与目标比较,如果相同完成,不同就交换一下数据和空格位置,加入二叉树,搜索下一个结果,直到没有步可走了,在搜索刚刚搜索到的位置的子位置,这样直到找到目标结果为止,函数:
bool CNineGird::ComputeFeel()
{
unsigned char *array = m_iChess;
UINT i;
const int MAXSIZE = 362880;
unsigned char temparray[9];
DWORD target , fountain , parent , parentID = 0 , child = 1;
ArrayToDword(m_iTargetChess , target);
ArrayToDword(array , fountain);
if (fountain == target)
{
return false;
}
if (m_pScanbuf != NULL)
{
delete[] m_pScanbuf;
}
m_pScanbuf = new Scanbuf[MAXSIZE];
AddTree(fountain ,m_pPlaceList);
m_pScanbuf[ 0 ].Place = fountain;
m_pScanbuf[ 0 ].ScanID = -1;
clock_t tim = clock();
while(parentID < MAXSIZE && child < MAXSIZE)
{
parent = m_pScanbuf[parentID].Place;
for ( i = 0 ; i < 4 ; i ++) // 0 :UP , 1:Down ,2:Left,3:Right
{
DwordToArray(parent , temparray);
if (MoveChess(temparray,i)) //是否移动成功
{
ArrayToDword(temparray , fountain);
if (AddTree(fountain, m_pPlaceList)) //加入搜索数
{
m_pScanbuf[ child ].Place = fountain;
m_pScanbuf[ child ].ScanID = parentID;
if (fountain == target) //是否找到结果
{
m_iTime = clock() - tim;
GetPath(child);//计算路径
FreeTree(m_pPlaceList);
delete[] m_pScanbuf;
m_pScanbuf = NULL;
return true;
}
child ++;
}
}
} // for i
parentID++;
}
m_iTime = clock() - tim;
FreeTree(m_pPlaceList);
delete[] m_pScanbuf;
m_pScanbuf = NULL;
return false;
}
重要函数的介绍结束;下面是程序的运行结果和运算结果:
‘柒’ 图形推理遍历是什么意思
是行测判断推理题中的重要考察题型,其中有个知识点叫作遍历。
图形推理的出题形式常见的有:一条式,两段式和九宫格。一条式常见的观察方式:是从左向右观察,问号处选择一个与所给图形规律一致的图形。
两段式的观察口诀是:第一段找规律,第二段应用规律。即观察第一段图形出现的规律,第二段结合前两个图形,最大限度地运用第一段的规律选择问号处图形;九宫格观察的方式:比较多样,常见的有横向、纵向和米字型、S型等。横(纵)向规律最为常见,即第一行找规律,第二行验证规律,第三行应用规律。
图形推理规律类考分为位置、样式、属性、数量、功能五大类。下面分类别为小伙伴们介绍下各个考点的识别特征和考查方式。
图形组成不同,但属性上呈现一致性时可以考虑属性类。属性类规律可分为对称性、曲直性和封闭性。对称性是属性类的考查重点。当题干图形比较规整时,可以考虑对称性,包括轴对称和中心对称。轴对称图形还可以进一步考查对称轴的数量、方向变化、图形中小元素的对称轴之间的位置变化、对称轴是否经过图形中的线/点等。
考查曲直性的图形其曲线和直线特征明显,但线条数量不一定明显,可能存在不好界定数量的线条,曲直性常与静态位置相结合考查。封闭性考查的频率不高,一般如果选项中出现一个图形的封闭性与其他三个明显不同时,可以考虑封闭性。
‘捌’ 数独(九宫格)解题技巧
楼上的那是最小的九宫格的技巧,数独最少是9个九宫格,根本不适用的。 . 每个人的习惯不一样,每个人的思维方法,惯性也不一样,根据自己的长处选择最好的办法才是真正的技巧。 . 1.联除法. 在并排的三个九宫格中的两排寻找相同数字,再利用九宫格得出另一排中该数字位置,该方法适用于中高级数独. 2.巡格法 找出在每个九宫格中出现频率较高的数字,得出该数字在其余九宫格内位置,该方法应用于方法一之后. 3.排它法 这个方法是解决问题的关键,易被常人所忽略.在各行列或九宫格中观察,若有个位置其它数字都不能填,就填余下的数字 4.待定法 此方法不常用却很有效.暂时确定某个数字在某个区域,再利用其来进行排除 5.行列法 此方法用于收官阶段,利用先从行列突破来提高解题效率. 6.假设法 作为一名高手,我不提倡这种方法.即在某个位置随机的填上一个数字,再进行推演,并有可能最终产生矛盾而否定结论. 7.频率法 这种方法相比于上一种方法更能提高效率.在某一行列或九宫格列举出所有情况,再选择某位置中出现频率高的数字 8.候选数法使用候选数法解数独题目需先建立候选数列表,根据各种条件,逐步安全的清除每个宫格候选数的不可能取值的候选数,从而达到解题的目的。 使用候选数法一般能解比较复杂的数独题目,但是候选数法的使用没有直观法那么直接,需要先建立一个候选数列表的准备过程,所以实际使用时可以先利用直观法进行解题,到无法用直观法解题时再使用候选数法解题。 候选数法解题的过程就是逐渐排除不合适的候选数的过程,所以在进行候选数删除的时候一定要小心,确定安全地删除不合适的候选数,否则,很多时候只有重新做题了。有了计算机软件的帮助,使得候选数表的维护变得轻松起来。 数独直观法解题技巧主要有:唯一候选数法、隐性唯一候选数法、区块删减法、数对删减法、隐性数对删减法、三链数删减法、隐性三链数删减法、矩形顶点删减法、三链列删减法、关键数删减法、关连数删减法。
‘玖’ 数独(九宫格)的规律是什么
规律:每一行、每一列、每一个粗线宫(3*3)内的数字均含1-9,不重复。
玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3*3)内的数字均含1-9,不重复。
九宫格游戏规则,1至9九个数字,横竖都有3个格,思考怎么使每行、每列两个对角线上的三数之和都等于15。这个游戏不仅仅考验人的数字推理能力,也同时考验了人的思维逻辑能力。
“重排九宫”有两种玩法:
第一种是在在3×3方格盘上,是把1至8八个小木块随意摆放,每一空格其周围的数字可移至空格。玩者要将小木块按12345678的顺序重新排好,以最少的移动次数拼出结果者为胜。
第二种玩法如九宫格算术游戏玩法,推动木格中8个数字排列,横竖都有3个格,使每行、每列两个对角线上的三数之和都等于15。在计算的同时,还必须思考怎么把数字方块推动到相对应的位置上,这个游戏不仅仅考验人的数字推理能力,也同时考验了人的思维逻辑能力。
以上内容参考:网络-九宫格
‘拾’ 九格拼图该怎么解决
你是想拼成这个样子吧:
1 2 3
4 5 6
7 8 0
如果按照九宫格拼图的规则,这是不可能的。
将九宫格拉成一行数,只考虑1-8八个数,你的图逆序数为3,是奇排列; 答案逆序数为0,是偶排列。九宫格的移动规则不会改变排列的奇偶性,故此题无解。这个证明需要一点数学知识,可以参考以下资料:
-------------------------------------------------
假设图中的a是3*3数字拼图标准的结果,则对于图b的状态是不可能变换成a的。证明起来需要用到高等代数里逆序数的概念,具体的说是用到了一个简单的定理。
定义:在一个1,2,...,n的排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。逆序数为偶数的排列称为偶排列;逆序数为奇数的排列称为奇排列。如2431中,21,43,41,31是逆序,逆序数是4,为偶排列。——这是北大《高等代数》上的定义。
定理:交换一个排列中的两个数,则排列的奇偶性发生改变。(证明见任何一本《高等代数》)
我们将空格看成数字9(数字9对应空位),按正常顺序看a图,9个数字排列是123456789,其逆序数是0,是偶排列;b图是123456879,逆序数是1,是奇排列。我们知道,我们能够移动空块相邻的块,这里的移动相当于一种特殊的对换(相邻对换),例如:对于b图,移动6就相当于9和6互换(9向上移动了),移动7就相当于9和7互换(9向左移动了)。现在假设从b图经过一系列的平移变到了a图,则空格块9必然移动(对换)了偶数次(向左一次必然要再向右一次回来,向上一次必然要向下再回来,最终才能够回到右下角的位置),根据上面的定理最终变成的排列必然是仍然是奇排列(和b相同),然而a图是偶排列,因而产生矛盾,因此b图不可能通过平移变成最终的a图。
(文中图片请参看【参考文献】中的链接。)
-------------------------------------------------
注:我还用迭代A*程序算了一下,遍历了39步之内所有拼法,没有解。这也印证了理论证明的结果。
【 参考文献】
网络:不可还原的拼图,http://ke..com/view/2879180.htm。