问题描述
3*3矩阵,1-9个数字每个数字只能使用一次,要求行列对角线的和都相等,如果仅能还原出一组可行的三阶幻方,则将其输出,否则输出“Too Many”(不包含引号)。
样例输入
0 7 2
0 5 0
0 3 0
0 5 0
0 3 0
样例输出
6 7 2
1 5 9
8 3 4
1 5 9
8 3 4
思路
这个题目比较简单,基本的深搜,标记用过的数字,回溯时取消。
卡的地方在于我一开始写dfs在里面用了两个循环遍历所有位置,再去找空的位置去填,这样导致了多个重复的结果,dfs的题目还是要多练才行。
正解是枚举每一个位置pos,位置已被占有时直接搜索下一个位置。
代码如下
#include<bits/stdc++.h>
using namespace std;
vector<int>a(10);
vector<int>num(10);
vector<int>v(10);
int flag=0;
bool check()
{
int sum=a[1]+a[2]+a[3];
if(a[4]+a[5]+a[6]!=sum||a[7]+a[8]+a[9]!=sum)return false;
if(a[1]+a[4]+a[7]!=sum||a[2]+a[5]+a[8]!=sum||a[3]+a[6]+a[9]!=sum)return false;
if(a[1]+a[5]+a[9]!=sum||a[3]+a[5]+a[7]!=sum)return false;
return true;
}
void dfs(int pos)
{
if(check()){
flag++;
if(flag==1){
for(int i=1;i<=9;i++)v[i]=a[i];
}
return;
}
if(a[pos]!=0)dfs(pos+1);
else{
for(int k=1;k<=9;k++){
if(num[k]==0){
a[pos]=k;
num[k]=1;
dfs(pos+1);
a[pos]=0;
num[k]=0;
}
}
}
}
int main()
{
for(int i=1;i<=9;i++){cin>>a[i];num[a[i]]=1;}
dfs(1);
if(flag==1){
for(int i=1;i<=9;i++){
cout<<v[i];
if(i%3==0){
cout<<endl;
}
else cout<<" ";
}
}
else cout<<"Too Many"<<endl;
return 0;
}