棋盘问题
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 29595 | Accepted: 14667 |
Description
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
Input
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
Output
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
Sample Input
2 1 #. .# 4 4 ...# ..#. .#.. #... -1 -1
Sample Output
2 1
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
//做到一半就卡住了,原因在于如果两个for循环,先扫行再扫列,扫完第一行,再扫第二行,那这样就会有重复的耶,后来想了个办法,输入有行号,按行号来
/*第一次提交lte超时 之前加了个for (i = hang; i < n; i++) 这个循环是不需要的,*/
#define MAXINT 10
int n = 0;
int k = 0;
int ans = 0;
char map[MAXINT][MAXINT];
int visithang[MAXINT];
int visitlie[MAXINT];
void init()
{
int i = 0;
int j = 0;
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
map[i][j] = '\0';
}
visithang[i] = 0;
visitlie[i] = 0;
}
ans = 0;
return;
}
void dfs(int hang,int num)
{
//int i = 0;
int j = 0;
if (num == k)
{
ans += 1;
return;
}
if (hang >n) return;
if ((n-hang) < (k-num)) return;//剩下的行数还不够棋子的个数,直接return
//for (i = hang; i < n; i++)
//{
for (j = 0; j < n;j++)
{
//if (1 == visithang[hang]) break;
if (1 == visitlie[j]) continue;
if ('.' == map[hang][j]) continue;
//visithang[i] = 1;
visitlie[j] = 1;
dfs(hang+1,num + 1);
//回溯
//visithang[i] = 0;
visitlie[j] = 0;
}
//}
/*4 2
#...
##..
...#
..#.
像这样的数据第一行第二行便利完,还得遍历第一行,第三行啊 */
dfs(hang+1,num ); //这个很关键,自己写的时候还是会有点参考,就是这样的,num不+1表示hang这行没放,比如第0行然后第1行,第一行不放就是第2行
return;
}
int main()
{
int i = 0;
int j = 0;
int num = 0;
freopen("input.txt","r",stdin);
while (2 == scanf("%d %d", &n, &k) && (-1 != n) && (-1 != k))
{
init();
for (i = 0; i < n;i++)
{
scanf("%s", &map[i]);
}
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if ('#' == map[i][j]) ans++;
}
}
if (1 != k)
{
ans = 0;
dfs(0,0); //从0行开始,后面那个是放置的棋子个数
}
printf("%d\n",ans);
}
return 0;
}
//第二次就这样糊里糊涂的通过了
#include <stdio.h> //POJ1321棋盘问题 #define MAXINT 10 char map[MAXINT][MAXINT]; int ans = 0; int n = 0; int w = 0; int visithang[MAXINT]; //表示哪行已经被占领了 int visitlie[MAXINT];//表示哪列已经被占领了 //棋盘问题不是一个很好解决的问题吗?怎么自己也卡盒了。。。。自己学了那么久就到底是在干嘛,今天开始要复习复习复习。。。 //这样就一次AC了,不相信啊不相信 void init() { int i = 0; int j = 0; for (i = 0; i < MAXINT; i++) { for (j = 0; j < MAXINT; j++) { map[i][j] = '\0'; } visithang[i] = 0; visitlie[i] = 0; } ans = 0; return; } void dfs(int x, int y, int num) //num表示放了几个棋子了 { int i = 0; int j = 0; if ((x<0)||(x>=w)||(y<0)||(y>=w)) return; if (num == n) { ans += 1; return; } for (i = x; i < w; i++) { for (j = 0; j < w; j++) { if (visithang[i]) continue; if (visitlie[j]) continue; if ('.' == map[i][j]) continue; visithang[i] = 1; visitlie[j] = 1; dfs(i,j,num+1); visithang[i] = 0; visitlie[j] = 0; } } //但是这样写不对耶。。。会有错误答案 //dfs(x+1, 0, 0); //防止有多行的出现,即行号比棋子多的情况 return; } //n <= 8 , k <= n因为最大只有8所以可以用DFS int main() { int i = 0; int j = 0; freopen("input.txt","r",stdin); while ((2 == scanf("%d %d",&w,&n))&&(-1 != w)&&(-1 != n)) { init(); for (i = 0; i < w;i++) { scanf("%s", &map[i]); } dfs(0, 0, 0); printf("%d\n",ans); } return 0; }