题目来源:http://noi.openjudge.cn/ch0205/323/
323:棋盘问题
总时间限制:1000ms 内存限制: 65536kB
描述
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
输入
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
输出
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
样例输入
2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1
样例输出
2
1
来源
蔡错@pku
-----------------------------------------------------
解题思路
网上好多博客都说要用深搜,但是最后还是用的自己的思路AC的,在百练的测试数据上用时4ms, 在poj的测试数据上用时297ms, 好像确实比深搜要慢一点。但是怎么说呢,对于自己来讲,自己的思路终归是清楚一点。
就是递归,每放一个棋子,就从棋盘上把这行这列删掉得到一个小棋盘,再对小棋盘计算一遍。为了避免重复(棋子都是一样的),在新的小棋盘上把这枚棋子上面的所有行都置为’*’,表示这些情况之前计算过了。还有就是每次只要遍历前(n-k+1)行,因为再往后剩下的行数比k还小,肯定放不下了。嗯,差不多就是这样。
-----------------------------------------------------
代码
//D:棋盘问题
//总时间限制: 1000ms 内存限制: 65536kB
//描述
//在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
//输入
//输入含有多组测试数据。
//每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
//当为-1 -1时表示输入结束。
//随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
//输出
//对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
//样例输入
//2 1
//#.
//.#
//4 4
//...#
//..#.
//.#..
//#...
//-1 -1
//样例输出
//2
//1
#include<iostream>
#include<fstream>
using namespace std;
int fac(int k)
{
int i = 1, ans = 1;
for (i=1; i<=k; i++)
{
ans *= i;
}
return ans;
}
int compute(char **mat, int n, int k)
{
int ii,i,j,jj,kk,kkk,cnt=0;
if (k==1)
{
for (i=0; i<n; i++)
{
for (j=0; j<n; j++)
{
if (mat[i][j] == '#')
{
cnt++;
}
}
}
return cnt;
}
if (n==1)
{
return 0;
}
char ** mat1 = new char*[n-1];
for (i=0; i<n-1; i++)
{
mat1[i] = new char[n-1];
}
kk = 0; kkk = 0;
for (ii = 0; ii<=n-k; ii++)
{
for (i=0; i<n; i++)
{
if (mat[ii][i] == '#')
{
kkk = 0;
for (j=0; j<n; j++)
{
if (j>ii)
{
kk = 0;
for (jj=0; jj<n; jj++)
{
if (jj != i)
{
mat1[kkk][kk] = mat[j][jj];
kk++;
}
}
kkk++;
}
else if (j<ii)
{
for (jj=0; jj<n-1; jj++)
{
mat1[kkk][jj] = '.';
}
kkk++;
}
}
cnt += compute(mat1,n-1,k-1);
}
}
}
for (i=0; i<n-1; i++)
{
delete[] mat1[i];
}
delete[] mat1;
return cnt;
}
int main()
{
#ifndef ONLINE_JUDGE
ifstream fin("tm201602D.txt");
int n,k,i,j;
fin >> n >> k;
while (n != -1 && k != -1)
{
char ** mat = new char*[n];
for (i=0; i<n; i++)
{
mat[i] = new char[n];
}
for (i=0; i<n; i++)
{
for (j=0; j<n; j++)
{
fin >> mat[i][j];
}
}
int ans = compute(mat,n,k);
cout << ans << endl;
for (i=0; i<n; i++)
{
delete[] mat[i];
}
delete[] mat;
fin >> n >> k;
}
fin.close();
return 0;
#endif
#ifdef ONLINE_JUDGE
int n,k,i,j;
cin >> n >> k;
while (n != -1 && k != -1)
{
char ** mat = new char*[n];
for (i=0; i<n; i++)
{
mat[i] = new char[n];
}
for (i=0; i<n; i++)
{
for (j=0; j<n; j++)
{
cin >> mat[i][j];
}
}
int ans = compute(mat,n,k);
cout << ans << endl;
for (i=0; i<n; i++)
{
delete[] mat[i];
}
delete[] mat;
cin >> n >> k;
}
return 0;
#endif
}