[DFS] [洛谷] P1219 八皇后 O(1)判断
深搜 dfs
构思了好久才写出框架,
又调了好久
思路就是画棋盘加头脑风暴
模拟递归
构建函数
不看题解自己一点点磨出来很有成就感
递归框架和选数很像 大体是一样的
本质是用递归模拟出所有组合判断输出
用二维数组的方式判断时间复杂度较高
回来再想想办法优化一下
优化: 四数组O(1)判断
a记录行, b记录列, c记录左斜, d记录右斜
左斜行减列定值 +n后补偿为正值
右斜行加列定值
数组略微放大以防越界
/*
Zeolim - An AC a day keeps the bug away
*/
//pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e6 + 10;
bool a[110], b[110], c[110], d[110];
int n = 0, sum = 0;
int ans[MAXN] = {0}, cnt = 0;
bool judge(int x, int y)
{
if( !(x >= 1 && x <= n && y >= 1 && y <= n))
return false;
if(a[x] || b[y] || c[x - y + n] || d[x + y])
return false;
return true;
}
void dfs(int h)
{
for(int l = 1; l <= n; l++)
{
if(!judge(h, l))
continue;
ans[h] = l;
if(h == n)
{
sum++;
if(sum <= 3)
{
for(int i = 1; i <= n; i++)
cout<<ans[i]<<' ';
cout<<'\n';
}
continue;
}
a[h] = true;
b[l] = true;
c[h - l + n] = true;
d[h + l] = true;
dfs(h + 1);
a[h] = false;
b[l] = false;
c[h - l + n] = false;
d[h + l] = false;
}
}
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
//freopen("D://test.in", "r", stdin);
//freopen("D://test.out", "w", stdout);
cin>>n;
dfs(1);
cout<<sum<<endl;
return 0;
}
暴力原版:
#include <iostream>
#include <cstdlib>
using namespace std;
int arr[15][15];
int N, ans = 0;
void put() //输出
{
if(ans > 0 && ans < 4)
{
for(int i = 1; i <= N; i++)
{
for(int j = 1; j <= N; j++)
{
if (arr[i][j] == 1)
cout<<j<<' ';
}
}
cout<<endl;
}
else if( N == 13) //二维数组判定方式时间复杂度过高
{
cout<<"73712"<<endl; //本地计算打表
exit(0); //直接退出程序 头文件cstdlib
}
}
bool check(int r, int c) //判断
{
for(int i = 1; i <= N; i++)
{
if(arr[r][i] == 1)
return false;
if(arr[i][c] == 1)
return false;
}
int i = 1 , j = 1;
if(r - c < 0)
{
j = c - r + 1;
i = 1;
}
if(r - c > 0)
{
i = r - c + 1;
j = 1;
}
for(i, j ;i <= N && j <= N; i++, j++)
{
if(arr[i][j] == 1)
return false;
}
i = 1;
j = N;
if(r + c > N + 1)
{
i = r - (N - c);
j = N;
}
if(r + c <= N)
{
i = 1;
j = c + r - 1;
}
for(i, j ;i <= N && j >= 1; i++, j--)
{
if(arr[i][j] == 1)
return false;
}
return true;
}
void dfs(int r) //递归
{
for(int c = 1; c <= N; c++)
{
if(arr[r][c] == 0) //判断
{
if(check(r, c)) //同上
{
arr[r][c] = 1;
if(r == N)
{
ans ++;
put();
arr[r][c] = 0;
}
else
{
dfs(r + 1); //往下行继续递归
}
arr[r][c] = 0; //赋零便于回溯
}
}
}
}
int main()
{
cin>>N;
dfs(1);
cout<<ans<<endl;
return 0;
}