小明最近在教鄰居家的小朋友國小奧數,而最近正好講述到了三階幻方這個部分。
三階幻方指的是将1~9不重複的填入一個33的矩陣當中,使得每一行、每一列和每一條對角線的和都是相同的。
三階幻方又被稱作九宮格,在國小奧數裡有一句非常有名的口訣:
“二四為肩,六八為足,左三右七,戴九履一,五居其中”,
通過這樣的一句口訣就能夠非常完美的構造出一個九宮格來。
4 9 2
3 5 7
8 1 6
有意思的是,所有的三階幻方,都可以通過這樣一個九宮格進行若幹鏡像和旋轉操作之後得到。
現在小明準備将一個三階幻方(不一定是上圖中的那個)中的一些數抹掉,交給鄰居家的小朋友來進行還原,并且希望她能夠判斷出究竟是不是隻有一個解。
而你呢,也被小明傳遞了同樣的任務,但是不同的是,你需要寫一個程式~
輸入
輸入一個33的矩陣,其中為0的部分表示被小明抹去的部分。
對于100%的資料,滿足給出的矩陣至少能還原出一組可行的三階幻方。
輸出
如果僅能還原出一組可行的三階幻方,則将其輸出,否則輸出“Too Many”(不包含引号)。
樣例輸入 Copy
0 7 2
0 5 0
0 3 0
樣例輸出 Copy
6 7 2
1 5 9
8 3 4
全排列比對,對1 ~9 ,9個數進行全排列,當遇到原數組有不為0的,并且與排列的數不同的,說明不滿足要求,continue
#include <iostream>
#include <algorithm>
using namespace std;
int a[10] = {1,2,3,4,5,6,7,8,9};
int b[10],temp[10],t[10];
int cnt;
int main()
{
for (int i =0 ; i < 9 ; i ++) cin >> b[i];
do
{
bool flag1 =false;
for (int i = 1; i <= 9 ; i ++)
{
if (b[i] && b[i] != a[i])
{
flag1 = true;
break;
}
}
if (flag1) continue;
int x1 =a[0] + a[1] + a[2];
int x2 =a[3] + a[4] + a[5];
int x3 =a[6] + a[7] + a[8];
int y1 =a[0] + a[3] + a[6];
int y2 =a[1] + a[4] + a[7];
int y3 =a[2] + a[5] + a[8];
int m = a[0] + a[4] + a[8];
int n = a[2] + a[4] + a[6];
if(x 1== x2 && x2 == x3)
{
if(x3 == y1 && y1 == y2 && y2 == y3)
{
if(y3 == m && m == n)
{
cnt ++;
for(int i = 0 ; i < 9 ; i ++)
temp[i] = a[i];
}
}
}
}while (next_permutation(a,a + 9));
if (cnt == 1)
{
for (int i = 0 ; i < 9 ; i ++)
{
cout << temp[i] << ' ';
if ((i + 1) % 3 == 0) cout << endl;
}
}
else puts("Too Many");
return 0;
}
DFS:
把9個數讀入到a[i]中去,每讀入一個數,就标記一下這個數是否為0,是否使用過;
dfs(1)從第一個位置還是深搜,
如果cnt > 1,傳回,如果st[x]這個位置的數不為0,不用填數字,dfs下一層;
枚舉1~9,9個數,如果這個數沒有被用過,就把這個數填進去;
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 15;
int a[N],b[N],ans[N];
bool st[N],used[N];
int cnt;
void check()
{
b[1] = a[1] + a[2] + a[3];
b[2] = a[4] + a[5] + a[6];
b[3] = a[7] + a[8] + a[9];
b[4] = a[1] + a[4] + a[7];
b[5] = a[2] + a[5] + a[8];
b[6] = a[3] + a[6] + a[9];
b[7] = a[1] + a[5] + a[9];
b[8] = a[3] + a[5] + a[7];
for (int i = 1 ; i <= 8 ; i ++) if (b[i] != 15) return;
cnt ++;
for (int i = 1 ; i <= 9 ; i ++) ans[i] = a[i];
}
void dfs(int x) //目前在第x個位置
{
if (cnt > 1) return;
if (x > 9)
{
check();
return;
}
if (st[x]) //目前這個位置已經有不為0的數字
{
dfs(x + 1);
return;
}
for (int i = 1 ; i <= 9 ; i ++)
{
if (!used[i])
{
a[x] = i;
used[i] = true;
dfs(x + 1);
used[i] = false;
}
}
}
int main()
{
for ( int i = 1 ; i <= 9 ; i ++)
{
cin >> a[i];
if (a[i])
{
st[i] = true;//标記i這個位置的數不為0
used[a[i]] = true; //标記a[i]這個數已經被用過
}
}
dfs(1);//從第一個位置開始深搜
if (cnt == 1)
{
for (int i = 1; i <= 9 ; i ++)
{
cout << ans[i] <<' ';
if (i % 3 == 0) cout << endl;
}
}
else puts("Too Many");
return 0;
}