hdu 2553 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2553
hdu 2553 皇后不能同行、列、斜线
一维数组求解
#include<iostream>
#include<cstring>
#include<queue>
#define maxn 12
using namespace std;
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
int n,ans;//ans方案数
int line[maxn];//line[1]=2表示第一行第二列放置了皇后
int a[maxn];//a数组用来存储方案数
void dfs(int x,int cnt)
{
//只需要考虑不同列还有对角线问题
if(cnt==n)
{
//找到一种可行方案
ans++;
return ;
}
for(int i=0;i<n;i++)
{
int flag=1;
line[x]=i;//皇后放在第x行第i列,若不能放置则会自动回溯不用考虑恢复现场
for(int j=0;j<x;j++)
{
//检验要放着的第x皇后是否与前面已放好的x-1皇后冲突
if(line[x]==line[j]||line[x]-x==line[j]-j||line[x]+x==line[j]+j)
{
//判断之前的列有没有放过,判断对角线有没有放皇后
flag=0;
break;
}
}
if(flag)
{
//仔细想想用不用恢复现场,答案是当然需要,在回溯时自动恢复现场了
dfs(x+1,cnt+1);
}
}
}
int main()
{
for(int i=1;i<=10;i++)
{
//打表,否则会超时
memset(line,0,sizeof(line));
ans=0,n=i;
dfs(0,0);
a[i]=ans;
}
while(cin>>n&&n)
{
//直接输出打表中的数据
cout<<a[n]<<endl;
}
return 0;
}
经典做法二维数组求解
#include<iostream>
#include<cstring>
#define maxn 12
using namespace std;
int n;
int map[maxn][maxn];
int a[maxn],ans;//a数组记录每种情况的方案数
int judge(int x,int y)
{
//判断x,y点处能否放置皇后
int i,j;
for(i=1;i<x;i++)
{
//排除不同行
if(map[i][y])
return 0;
}
for(i=x-1,j=y+1;i>=1&&j<=n;i--,j++)
{
//排除45度斜线
if(map[i][j])
return 0;
}
for(i=x-1,j=y-1;i>=1&&j>=1;i--,j--)
{
//排除135度斜线
if(map[i][j])
return 0;
}
return 1;
}
void dfs(int x)
{
if(x==n+1)
{
//摆放完成方案数加一
ans++;
return ;
}
for(int i=1;i<=n;i++)
{
//尝试固定行的不同列
if(judge(x,i)&&!map[x][i])
{
map[x][i]=1;//标记
dfs(x+1);
map[x][i]=0;//回溯
}
}
}
int main()
{
for(int i=1;i<=10;i++)
{
//提前打表
memset(map,0,sizeof(map));
ans=0;
n=i;
dfs(1);
a[i]=ans;
}
while(cin>>n&&n)
cout<<a[n]<<endl;
return 0;
}
acwing 843 题目链接: https://www.acwing.com/problem/content/845/
acwing 843 皇后不能同行、列、斜线
#include <iostream>
#include <cstring>
#define maxn 10
using namespace std;
int n;
int line[maxn];//line[1]=2表示第一行第二列放置了皇后
void dfs(int x)
{
//只需要考虑不同列还有同斜线问题
int i,j;
if(x==n+1)
{
//摆放完成,输出结果
for(i=1;i<=n;i++)
{
for(j=1;j<=n-1;j++)
{
if(j==line[i])
cout<<"Q";
else
cout<<".";
}
if(j==line[i])
cout<<"Q"<<endl;
else
cout<<"."<<endl;
}
cout<<endl;
}
for(i=1;i<=n;i++)
{
//遍历这一行所有能放的列
int flag=1;
line[x]=i;//皇后放在第x行第i列
for( j=1;j<x;j++)
{
//检验要放着的第x皇后是否与前面已放好的x-1皇后冲突
if(line[j]==line[x]||abs(x-j)==abs(line[x]-line[j]))
{
//判断之前的列有没有放过,判断斜线有没有放皇后
flag=0;
break;
}
}
if(flag)
{
//仔细想想用不用恢复现场,答案是当然需要,在回溯时自动恢复现场了
dfs(x+1);
}
}
}
int main(int argc, char const *argv[])
{
cin>>n;
dfs(1);//从第一行开始深搜,不用考虑同行问题
return 0;
}
洛谷1219 题目链接:https://www.luogu.com.cn/problem/P1219
优化的dfs
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#define maxn 15
using namespace std;
int n,ans;
int line[maxn],a[2*maxn],b[2*maxn],c[2*maxn];
//a数组用来判断这一列是否放置皇后
//b表示的是左下到右上的对角线;
//c表示的是左上到右下的对角线;
void dfs(int x)
{
if(x==n+1)
{
ans++;
if(ans<=3)
{
for(int i=1;i<n;i++)
{
printf("%d ",line[i]);
}
printf("%d\n",line[n]);
}
return ;
}
for(int i=1;i<=n;i++)
{
//优化,不用两层循环
if(!a[i]&&(!b[x+i])&&(!c[x-i+n]))
{
line[x]=i;//之前是试探防止,现在优化
a[i]=1;
b[x+i]=1;
c[x-i+n]=1;
dfs(x+1);
//回溯
a[i]=0;
b[x+i]=0;
c[x-i+n]=0;
}
}
}
int main()
{
scanf("%d",&n);
dfs(1);
printf("%d\n",ans);
return 0;
}