题目
dfs()解决方法
#include<bits/stdc++.h>
using namespace std;
int a[5][5]/*输入的矩阵*/,ans[5][5];/*输出的矩阵*/
int n/*记录的0的位置*/,cnt=0;/*记录解的个数*/
int vis[10];/*标记用过的数字*/
pair <int,int> p[10];//储存0的位置
bool check(){//检查是不是九宫幻方
int sum=a[1][1]+a[2][2]+a[3][3];//对角线和
if(sum!=a[1][3]+a[2][2]+a[3][1]) return false;//正副对角线是否相等
for(int i=1;i<=3;i++){
int temp1=0;//行的和
int temp2=0;//列的和
for(int j=1;j<=3;j++){
temp1+=a[i][j];
temp2+=a[j][i];
}
if(temp1!=sum||temp2!=sum) return false;/*比较每一行和每一列相不相等*/
}
//如果以上都过了说明是九宫幻方
return true;
}
void dfs(int now){
if(now>n){//满足此条说明填满了所有空位
if(check()){//检查是不是九宫幻方。是:ans[][]存储输出,否:跳出去执行35行代码
cnt++;
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
ans[i][j]=a[i][j];
}
}
}
}
int x=p[now].first;int y=p[now].second;
for(int k=1;k<=9;k++){
if(vis[k]) continue;
a[x][y]=k;
vis[k]=1;
dfs(now+1);
//回溯过程,只有在check()不满足条件时才触发。
a[x][y]=0;
vis[k]=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]) p[++n]=make_pair(i,j);//如果a[i][j]位置为0则把这个位置记录下来。利用p[++n]=make_pair(i,j)可以很好的把位置为0的个数和位置很好的结合起来
vis[a[i][j]]=1;//标记用过的数字,例如a[i][j]=3则vis[3]=1,则说明3已经用过。
}
}
dfs(1);
if(cnt == 1) { // 九宫幻方的个数为 1,直接输出 ans 记录的矩阵
for(int i = 1 ; i <= 3 ; i ++)
for(int j = 1 ; j <= 3 ; j ++)
cout << ans[i][j] << " \n"[j == 3];
} else cout << "Too Many\n"; // 九宫幻方的个数为 2 则输出 Too Many
return 0;
}
详细解释dfs(now+1)
全排列解决方法
#include<bits/stdc++.h>
using namespace std;
int ans[5][5];//如果有1个把它输出
//输入
int a[5][5],b[5][5],p[10];//a是输入的参考样例,b是咱自己列举的,p是到时候赋值用
signed main(){
int cnt=0;//解的个数。
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
cin>>a[i][j];
}
}
for(int i=0;i<=9;i++){
p[i]=i;
}
//列出全排列然后对照然后判断是不是九宫幻方
do{
//最开始的排列。
b[1][1]=p[1],b[1][2]=p[2],b[1][3]=p[3];
b[2][1]=p[4],b[2][2]=p[5],b[2][3]=p[6];
b[3][1]=p[7],b[3][2]=p[8],b[3][3]=p[9];
bool flag=true;//假定与a[][]提出的题目符合
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
if(a[i][j]==0)continue;//不比较非零的部分
if(a[i][j]!=b[i][j])flag=false;//不等
}
}
if(flag==false)continue;//这里我们会发现flag的真正用意:在我们发现里面的参考样例与我们排列出来的有不一样的时,就可以直接跳出do_while()这层大循环所以要写外面。
//到这里说明符合参考样例格式,下面判断是不是九宫幻方
//先看对角线
bool ok=true;//true是矩阵
int sum=0;
sum=b[1][1]+b[2][2]+b[3][3];
if(sum != b[3][1]+b[2][2]+b[1][3])continue;
//再看行和列
for(int i=1;i<=3;i++){
int tmp1=0;
int tmp2=0;
for(int j=1;j<=3;j++){
tmp1 +=b[i][j],/*行的和*/ tmp2 +=b[j][i];/*列的和*/
}
if(tmp1 != sum||tmp2 != sum) ok=false;//符合题意,解加1
}
if(!ok) continue;
cnt++;
if(cnt>=2)return cout<<"TOO Many\n",0;
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
ans[i][j]=b[i][j];
}
}
}while(next_permutation(p+1,p+1+9));
//按照提议看有几个解,一个输出多个TOO MANY。
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
cout<<ans[i][j]<<"\n"[j%3!=0]<<" "[j%3==0];
}
}
return 0;
}