八皇后问题(递归)

八皇后

题目很狗,下面这段代码过不去,为啥呢?
``因为这句话。。。
在这里插入图片描述
啊啊啊啊啊啊啊啊啊啊啊啊啊~搞出来了,只是在输出时把chess[i][j]改成chess[j] [i],这不就是旋转90度的事吗?
但我还是不明白为什么这种递归做出来的都要旋转90°

这那里能只凭给的几个sample就下手给他旋转90°呢?
这哪里能想的到呢?
再去看看别人用别的方法怎么做。。。

#include <iostream>
#include <stdlib.h>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int chess[8][8]={0};
int count=0;
void print(){
	printf("No. %d\n",count);
	for(int i=0;i<8;i++){
		for(int j=0;j<8;j++){
			printf("%d ",chess[i][j]);
		}
		printf("\n");
	}
	return;	
}
int safe(int row,int col){//假设选择把第row行的皇后放在col列位置,
//那么这一行不用担心,只要看看这一列上有没有之前已经放好的皇后 
	int i,j,k;
	for(i=0;i<8;i++){
		if(chess[i][col]==1)return 0;
	}
	for(j=row,k=col;j>=0&&k>=0;j--,k--){
			if(chess[j][k]==1)return 0;
	}
	for(j=row,k=col;j>=0&&k<8;j--,k++){
			if(chess[j][k]==1)return 0;
	}
	return 1;
}
void nQueen(int row){//假设前row-1行的皇后已经排列好了 
	if(row==8){
		++count;
	print();
	return ;
	}
//	else{
		for(int col=0;col<8;col++){
		
			if(safe(row,col)){
					chess[row][col]=1;
					nQueen(row+1);
//	成功的给第row行皇后安排了一个位置col并且成功的把它送入了接下来一行的安排
//但要知道,针对第row行可能不止col这一个合适的位置,走完了这条路之后,
//还要看看其他7条路,即假设不走这条路,等到col+1了再走
//就像之前俺总结的,一个递归里面多条路,如果vis数组(这里是chess)
//是用来限制一条路上不能重走的,那么每走完一条路都要将vis数组重置为0 
					chess[row][col]=0;
			}	 
		}
//	}
}
int main(int argc, char** argv) {
	nQueen(0);
	return 0;
}
#include <bits/stdc++.h>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
//int chess[8][8];
int arr[8];//arr[i]表示第i行防的位置中列数 
int cnt=0;
void print(){
	printf("No. %d\n",cnt);
	for(int i=0;i<8;i++){//对于第i行 
		for(int j=0;j<8;j++){
//			printf("%d ",chess[i][j]);
			cout << ((arr[j] == i) ? 1 : 0) << " ";
		}
		printf("\n");
	}
	return;	
}
int safe(int row,int col){//假设选择把第row行的皇后放在col列位置,
//那么这一行不用担心,只要看看这一列上有没有之前已经放好的皇后 
	int i,j,k;
	for(i=0;i<row;i++){//正上方 
//		if(chess[i][col]==1)return 0;
		if(arr[i]==arr[row])return 0;//别的行也有放在这一列的 
		if(abs(arr[row]-arr[i])==row-i)return 0;
	}
//	for(j=row,k=col;j>=0&&k>=0;j--,k--){//左上 
//			if(chess[j][k]==1)return 0;
//	}
//	for(j=row,k=col;j>=0&&k<8;j--,k++){//右上 
//			if(chess[j][k]==1)return 0;
//	}
	return 1;
}
void nQueen(int row){//假设前row-1行的皇后已经排列好了 
	if(row==8){
		++cnt;
	print();
	return ;
	}
//	else{
		for(int col=0;col<8;col++){
			arr[row]=col; //假设放在col位置必须先设置 arr[row]才能判断safe噢
//而之前判断safe是通过把col参数传进safe函数的,这里可以不用col这个参数 
			if(safe(row,col)){
//					chess[row][col]=1;
					nQueen(row+1);
//					chess[row][col]=0;
//反正也不会干扰在第row行别的列放皇后的情况,因为直接arr[row]覆盖掉之前情况 
			}	 
		}
//	}
}
int main(int argc, char** argv) {
//	memset(chess,0,sizeof(chess)) ;
	memset(arr,0,sizeof(arr)) ;
	nQueen(0);
	return 0;
}

走行数大于棋子数的棋盘

#include <bits/stdc++.h>		
using namespace std;
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
int chess[10][10];
	int n,k;
	int ans;
int vis[10];//标记第i列是否放了棋子 
void dfs(int m,int index){//八皇后问题要选的只是列,这里还需要选行 
	if(m==k+1){
		ans++;
		return; 
	}
	for(int j=index;j<n;j++){
		for(int i=0;i<n;i++){
			if(!vis[i]&&chess[j][i]==1){
				vis[i]=1; 
				dfs(m+1,j+1);//把第m枚棋子放在了第i列,接下来安排第i+1枚棋子
				vis[i]=0; //考虑完了 把第m枚棋子放在了第i列的情况,接下来考虑放在i+1列
	//	,放在第i列的痕迹自然是要抹去的 
			} 
		}
	}

}
//模拟八皇后思想大概这样,但此题还需要考虑放在哪些行 ,而且放棋子时需要考虑
//chess[?][i]==1?,对于第m枚棋子,可以放在第几行呢 
//dfs函数多加一个参数index表示从index行开始找,开始是第0行
//当然第0行可以不放,在这之下找一行 ,不用担心按这样棋子放不下,放不下时dfs
//中循环条件index>n自然结束循环,m也不会走完k而增加ans 
int main(){
	while(cin>>n>>k){//k<=n
		if(n==-1&&k==-1)break;
		ans=0;
		memset(vis,0,sizeof(vis));
		char ch;
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				cin>>ch;
				if(ch=='.')chess[i][j]=0;
				else chess[i][j]=1;
			}
		}
		dfs(1,0);//八皇后是安排那八行中每行的棋子放在第几列,这里安排k枚棋子,从第一枚开始 
		cout<<ans<<endl;
	}
    return 0;
}

马走日

1490:A Knight’s Journey
//这题面还挺讨厌的。。。
//lie用英文字母表示,行用阿拉伯数字表示,走的规则是象棋里的 马走日 ,
//目的是看能否踏遍给定尺寸棋盘每个点
//哦凑,自诩英文不错,这道题真的搞蒙我了,从题目压根没看出行列到底哪个是用英文字母表示
//大概,列是用字母表示,按照字典序就是列要优先地小
//int dx[8]={-2,-2,-1,-1,1,1,2,2};
//int dy[8]={-1,1,-2,2,-2,2,-1,1};
//最后输出坐标还是先列后行 shirt!

#include <bits/stdc++.h>		
using namespace std;
//#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
int p,q; 
int area;
int flag=0;
//int dx[]={} 
//int dy[]={} 
const int N=30;
int vis[N][N];
//int dw[8][2]={{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2}};
int dw[8][2]={{-1,-2},{1,-2},{-2,-1},{2,-1},{-2,1},{2,1},{-1,2},{1,2}};
struct kkk{
	int x;
	int y;
};
kkk w[N*N]; 
void dfs(int x,int y,int step){
	if(flag==1)return; //已经成功踏遍,可能有的点还没机会也没必要遍历八方啦 
	w[step].x=x;
	w[step].y=y;
	if(step==area){
		flag=1;
		return;
	}
	for(int i=0;i<8;i++){
		int cx=x+dw[i][0];
		int cy=y+dw[i][1];
		if((cx>=1)&&(cx<=p)&&(cy>=1)&&(cy<=q)){
			if(vis[cx][cy]==0){
			vis[cx][cy]=1;
			dfs(cx,cy,step+1); 
			vis[cx][cy]=0;
			}
		}
	}
}
int main(){
	int t;
	scanf("%d",&t);
	for(int i=1;i<=t;i++){
//		cin>>p>>q;//表示棋盘有p行q列 
		scanf("%d %d",&p,&q);
		memset(vis,0,sizeof(vis));
		vis[1][1]=1;//从位置1,1出发嘛,从此只看八方位置 
		flag=0;//从1,1开始深度搜索,每个点遍历八方之后看能否踏遍所有位置 
		area=p*q;
		dfs(1,1,1);//step代表踏过的步数啦=走动步数加上最开始的1 
		printf("Scenario #%d:\n",i);
		if(flag==1){//要输出走过的那些点,因此还要记录走过的点坐标 
			for(int j=1;j<=area;j++){
				printf("%c%d",w[j].y+'A'-1,w[j].x);
			}
			printf("\n");
		} 
		else {
			printf("impossible\n");
		}
			printf("\n");
	}
    return 0;
}
//这题面还挺讨厌的。。。
//lie用英文字母表示,行用阿拉伯数字表示,走的规则是象棋里的 马走日 ,
//目的是看能否踏遍给定尺寸棋盘每个点 
//哦凑,自诩英文不错,这道题真的搞蒙我了,从题目压根没看出行列到底哪个是用英文字母表示
//大概,列是用字母表示,按照字典序就是列要优先地小
//int dx[8]={-2,-2,-1,-1,1,1,2,2};
//int dy[8]={-1,1,-2,2,-2,2,-1,1};
//最后输出坐标还是先列后行 shirt! 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值