n皇后问题 hdu2553+acwing 843+luogu 1219

11 篇文章 0 订阅
11 篇文章 0 订阅

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值