百练/ 北京大学2016研究生推免上机考试(校外)D: 棋盘问题(递归)

题目来源: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
#include
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; iii)
					{
						kk = 0;
						for (jj=0; jj> n >> k;
	while (n != -1 && k != -1)
	{
		char ** mat = new char*[n];
		for (i=0; i> mat[i][j];
			}
		}
		int ans = compute(mat,n,k);
		cout << ans << endl;
		for (i=0; i> 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> mat[i][j];
			}
		}
		int ans = compute(mat,n,k);
		cout << ans << endl;
		for (i=0; i> n >> k;
	}
	return 0;
#endif
}


你可能感兴趣的:(百练OJ/poj,基础算法)