问题:17 棋盘多项式
问题描述:
八皇后问题是在棋盘上放皇后,互相不攻击,求方案。变换一下棋子,还可以有八车问题,八马问题,八兵问题,八王问题,注意别念反。在这道题里,棋子换成车,同时棋盘也得换,确切说,是进行一些改造。比如现在有一张n*n的棋盘,我们在一些格子上抠几个洞,这些洞自然不能放棋子了,会漏下去的。另外,一个车本来能攻击和它的同行同列。现在,你想想,在攻击的过程中如果踩到一个洞,便会自取灭亡。故,车的攻击范围止于洞。
此题,给你棋盘的规模n,以及挖洞情况,求放k个车的方案数(k从0到最多可放车数)
输入说明 :
第一行一个整数n表示棋盘大小
接下来n行,每行n个用空格隔开的数字0或1,0的形状表示洞,1表示没有洞
数据规模和约定
n<=8
输出说明 :
若干行,第i行表示放i个车的方案数
输入范例 :
3
1 0 1
1 1 1
1 0 1
输出范例 :
7
12
4
思路:
又是类似8皇后的题,一开始我并没有在判断能否放车的上面调用自身
而是判断如果不能放车再调用Dfs(row,cow+1,carCount,counter);
结果纠错了好久,不能这样写的原因就是因为这样写的话只能拿到一种情况
而事实上我们要考虑每个位置放与不放的所有情况,还是经验不足啊
代码实现:
#include<bits/stdc++.h>
using namespace std;
int **chessboard;
int n;
vector<int> res;
bool Check(int row,int cow)
{
if(chessboard[row][cow]==2 || chessboard[row][cow]==0) return false;
//因为按先加列再加行的顺序,所有只用检查左方和上方
//检查上方
for(int i=row-1;i>=1;i--)
{
if(chessboard[i][cow]==0) break;
if(chessboard[i][cow]==2) return false;
}
//检查左方
for(int i=cow-1;i>=1;i--)
{
if(chessboard[row][i]==0) break;
if(chessboard[row][i]==2) return false;
}
return true;
}
void Dfs(int row,int cow,int carCount,int counter)
{
if(counter==0)
{
res[carCount]++;
return;
}
if(cow>n)
{
cow=1;
row+=1;
}
if(row==n+1)
{
return;
}
//当前位置不放车
Dfs(row,cow+1,carCount,counter);
//当前位置可以放车就放车
if(Check(row,cow))
{
chessboard[row][cow]=2;
Dfs(row,cow+1,carCount,--counter);
chessboard[row][cow]=1;
}
}
int main()
{
cin>>n;
chessboard = new int*[n+1];
res.push_back(0);
for(int i=1;i<=n;i++)
{
chessboard[i]=new int[n+1];
for(int j=1;j<=n;j++)
{
cin>>chessboard[i][j];
}
}
while(true)
{
res.push_back(0);
Dfs(1,1,res.size()-1,res.size()-1);
if(res[res.size()-1]==0)
break;
cout<<res[res.size()-1]<<endl;
}
}