理解:棋盘上先写满0,然后枚举的时候就像离散数学里面按照从二进制从大到小写真值表那样
如:
2.在调用递归的时候,dfs(24)是最后一个位置(5*5)棋盘,则还会调用dfs(25),这里dfs(25)的作用:在棋盘满的时候返回
#include<iostream>
using namespace std;
int mp[5][5]; // 定义一个5x5的矩阵,用于存储0和1
long long sum=0; // 用于统计满足条件的排列数量
// 检查函数,用于验证当前矩阵是否满足条件
void check(){
int a=0; // 用于统计矩阵中1的个数
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
if(mp[i][j]==1) a++; // 统计1的数量
}
}
if(a!=13) return; // 如果1的个数不是13,不满足条件,直接返回
// 检查主对角线和副对角线的和是否为5的倍数
int count=0;
count += mp[0][0] + mp[1][1] + mp[2][2] + mp[3][3] + mp[4][4]; // 主对角线和
if(count % 5 == 0) return; // 如果主对角线和为5的倍数,不满足条件
count = 0; // 重置count
count += mp[0][4] + mp[1][3] + mp[2][2] + mp[3][1] + mp[4][0]; // 副对角线和
if(count % 5 == 0) return; // 如果副对角线和为5的倍数,不满足条件
count = 0; // 重置count
// 检查每一行和每一列的和是否为5的倍数
for(int i=0;i<5;i++){
count = mp[i][0] + mp[i][1] + mp[i][2] + mp[i][3] + mp[i][4]; // 行和
if(count % 5 == 0) return; // 如果行和为5的倍数,不满足条件
count = 0; // 重置count
count = mp[0][i] + mp[1][i] + mp[2][i] + mp[3][i] + mp[4][i]; // 列和
if(count % 5 == 0) return; // 如果列和为5的倍数,不满足条件
count = 0; // 重置count
}
// 如果所有检查都通过,增加满足条件的排列数量
sum++;
}
// 深度优先搜索函数,用于生成所有可能的矩阵排列
void dfs(int num){ // num表示当前填充的位置编号
if(num == 25){ // 如果棋盘已满(5x5棋盘共有25个位置)
check(); // 检查当前排列是否满足条件
return;
}
int x = num / 5, y = num % 5; // 将位置编号转换为棋盘上的坐标
mp[x][y] = 0; // 先尝试在当前位置放置0
dfs(num + 1); // 递归填充下一个位置
mp[x][y] = 1; // 再尝试在当前位置放置1
dfs(num + 1); // 递归填充下一个位置
}
int main(){
dfs(0); // 从位置0开始,遍历所有可能的排列
cout << sum; // 输出满足条件的排列数量,预期结果为3126376
return 0;
}
#include<bits/stdc++.h>
using namespace std;
long long ans=0;
int mp[5][5];
void check()
{
int a=0;
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
{
if(mp[i][j]==1) a++;
}
}
if(a!=13) return ;
int cnt=0;
for(int i=0;i<5;i++)
{
cnt+=mp[i][i];
}
if(cnt%5==0) return ;
cnt=0;
for(int i=0;i<5;i++)
{
cnt+=mp[i][4-i];
}
if(cnt%5==0) return ;
cnt=0;
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
{
cnt+=mp[i][j];
}
if(cnt%5==0) return ;
cnt=0;//这个清零放置的位置是特别注意的
//当计算完成之后判断,若非法则返回,否则清零进行下一次计算
}
//若将清零放在for循环外面,则不是判断每一行是否合法
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
{
cnt+=mp[j][i];
}
if(cnt%5==0) return ;
cnt=0;
}
ans++;
}
void dfs(int num)
{
if(num==25)
{
check();
return ;
}
int x=num/5,y=num%5;
mp[x][y]=1;
dfs(num+1);
mp[x][y]=0;
dfs(num+1);
}
int main()
{
dfs(0);
cout<<ans;
return 0;
}
设置cnt是为了判断,
对每行、每列、对角线进行判断。
但需要需要注意的是,每一行和每一列不同与对角线的是对角线只有一个for循环,在for循环之外添加检查。
但是每行(列)有两层循环,需要在第一层循环设检查,这个要注意逻辑。不能设置在外面。
#include<bits/stdc++.h>
using namespace std;
long long ans=0;
int mp[5][5]={};
void check()
{
int a=0;
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
if(mp[i][j]==1) a++;
}
if(a!=13) return ;
int cnt=0;
for(int i=0;i<5;i++)
{
cnt+=mp[i][i];
}
if(cnt%5==0) return ;
cnt=0;
for(int i=0;i<5;i++)
{
cnt+=mp[i][4-i];
}
if(cnt%5==0) return ;
cnt=0;
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
cnt+=mp[j][i];
if(cnt%5==0) return ;
cnt=0;
}
;
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
cnt+=mp[i][j];
if(cnt%5==0) return ;
cnt=0;
}
ans++;
}
void dfs(int num)
{
if(num==25)
{
check();
return ;//??
}
int x=num/5,y=num%5;
mp[x][y]=1;
dfs(num+1);
mp[x][y]=0;
dfs(num+1);
}
int main()
{
dfs(0);
cout<<ans;
return 0;
}