算法提高 棋盘多项式

博客围绕带洞棋盘的放车问题展开。给定n*n棋盘,部分格子有洞不能放车,车攻击范围止于洞。要求根据棋盘规模n和挖洞情况,求出放k个车(k从0到最多可放车数)的方案数,并给出了输入输出格式、样例及数据规模约定。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

  八皇后问题是在棋盘上放皇后,互相不攻击,求方案。变换一下棋子,还可以有八车问题,八马问题,八兵问题,八王问题,注意别念反。在这道题里,棋子换成车,同时棋盘也得换,确切说,是进行一些改造。比如现在有一张n*n的棋盘,我们在一些格子上抠几个洞,这些洞自然不能放棋子了,会漏下去的。另外,一个车本来能攻击和它的同行同列。现在,你想想,在攻击的过程中如果踩到一个洞,便会自取灭亡。故,车的攻击范围止于洞。
  此题,给你棋盘的规模n,以及挖洞情况,求放k个车的方案数(k从0到最多可放车数)

输入格式

  第一行一个整数n表示棋盘大小
  接下来n行,每行n个用空格隔开的数字0或1,0的形状表示洞,1表示没有洞

输出格式

  若干行,第i行表示放i个车的方案数

样例输入

3
1 0 1
1 1 1
1 0 1

样例输出

7
12
4

数据规模和约定

  n<=8

#include<iostream>
using namespace std;
int n;
int arr[10][10];//棋盘状态
int res[100]; //目标,统计从放1个车和n*n-1个车的种类数

bool check(int x,int y){
	for(int i=x-1;i>=0;i--)//判断从(x-1,y) ~(0,y) 坐标位置 逆向遍历
		if(arr[i][y]==2)//如果先遇到的是2(坐标上的数字为2表示此处已经放置了车),说明两个2之间没有 洞,那么这个位置是不能再放 车
			return false;
		else if(arr[i][y]==0)//如果先遇到了洞,就说明从(x-1,y) ~(0,y) 坐标位置,在洞之后是可以放置车的,所以该范围没有问题,于是跳出循环,判断下一个范围
			break;

	for(int i=x+1;i<n;i++)//判断从(x+1,y) ~(n-1,y) 坐标位置 逆向遍历
		if(arr[i][y]==2)
			return false;
		else if(arr[i][y]==0)
			break;

	for(int i=y-1;i>=0;i--)/判断从(x,y-1) ~(x,0) 坐标位置 逆向遍历
		if(arr[x][i]==2)
			return false;
		else if(arr[x][i]==0)
			break;

	for(int i=y+1;i<n;i++)/判断从(x,y+1) ~(x,n-1) 坐标位置 逆向遍历
		if(arr[x][i]==2)
			return false;
		else if(arr[x][i]==0)
			break;

	return true;
}
//now用来遍历棋盘,sum是统计放置的车的数量
void dfs(int now,int sum){
	if(now>=n*n){//当一次遍历结束时
		res[sum]++;	
		return;
	}
	int x=now/n;//此处与输入棋盘状态一样,巧妙解决了两层循环遍历棋盘的问题
	int y=now%n;
	if(arr[x][y]==1)//当(x,y)位置为1,即能放车时
		if(check(x,y)){//判断该位置是否符合条件
			arr[x][y]=2;//标记该位置
			dfs(now+1,sum+1);//遍历下个位置,车的数量加1
			arr[x][y]=1;//回溯
		}
	dfs(now+1,sum);//如果该位置无法放车,那么遍历下个位置,车的数量不变
}
int main(){
	cin>>n;
	int nn=0;
        //输入棋盘状态,只用一层循环,此种方法很巧妙
        //n=3时,nn=0~8 i=0~2,j=0~2
	while(nn<n*n){
		int i=nn/n;
		int j=nn%n;
		cin>>arr[i][j];
		nn++;
	}
	dfs(0,0);
	for(int i=1;i<n*n;i++){
		if(res[i]!=0)
			cout<<res[i]<<endl;
		else
			break;
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值