题目描述

在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放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

又是一道见到标题就知道是哪个类型的题目:-  与8皇后问题类似,但又不完全一样。少了斜向判断,但是k 不等于n 了。

如果k = n,那么:

#include<stdio.h>
#include<string.h>
int map[][];
int vis[];
int ans, k, n;
void dfs(int, int);
int main(void)
{
while(scanf("%d%d", &n, &k))
{
if(n == - && k == -)
break;
memset(map, , sizeof(map));
memset(vis, , sizeof(vis));
for(int row = ; row <= n; row++)
for(int col = ; col <= n; col++)
scanf(" %c", &map[row][col]); // %c前面的空格用于过滤空白符(换行/空格/制表) ans = ;
dfs(, );
printf("%d\n", ans);
}
return ;
} void dfs(int row, int count) // count为已经放置的棋子数
{
if(count == k)
{
ans++;
return;
} for(int col = ; col <= n; col++)
{
if(map[row][col] == '#' && !vis[col])
{
vis[col] = ; // 1表示当前列已占据
dfs(row+, count+);
vis[col] = ; // 取消标志
}
}
}

但是题目要求k ≤ n,因此有:

#include<stdio.h> // 40MS
#include<string.h>
int map[][];
int vis[]; // 拜访过的列,置0表示未访问
int ans, k, n;
void dfs(int, int);
int main(void)
{
while(scanf("%d%d", &n, &k))
{
if(n == - && k == -)
break;
memset(map, , sizeof(map));
memset(vis, , sizeof(vis));
for(int row = ; row <= n; row++)
for(int col = ; col <= n; col++)
scanf(" %c", &map[row][col]); // %c前面的空格用于过滤空白符(换行/空格/制表) ans = ;
dfs(, );
printf("%d\n", ans);
}
return ;
} void dfs(int row, int count) // row为将要放置棋子的行数,count为已经放置的棋子数
{
if(count == k)
{
ans++;
return;
}
if(row > n)
return;
for(int col = ; col <= n; col++)
{
if(map[row][col] == '#' && !vis[col])
{
vis[col] = ; // 1表示当前列已占据
dfs(row+, count+);
vis[col] = ; // 取消标志
}
} dfs(row+, count);
}

该程序和最前面那个程序主要有两处不同,row > n 用来防止数组下标越界,因为最前面那个程序行和列同时增加,而后者存在只有行增的情况。应该可以看出count == k 和row > n 从一定程度上来说就是用来防止无限递归的。此外,该程序耗时40MS,是因为我们还没有剪枝,下面我写了一个0MS的:

#include<stdio.h> // 0MS
#include<string.h>
int map[][];
int vis[];
int ans, k, n;
void dfs(int, int);
int main(void)
{
int can_put;
while(scanf("%d%d", &n, &k))
{
if(n == - && k == -)
break;
memset(map, , sizeof(map));
memset(vis, , sizeof(vis));
can_put = ;
for(int row = ; row <= n; row++)
for(int col = ; col <= n; col++)
{
scanf(" %c", &map[row][col]); // %c前面的空格用于过滤空白符(换行/空格/制表)
if(map[row][col] == '#')
can_put++;
}
if(can_put < k) // 定界剪枝
{
printf("0\n");
continue;
}
ans = ;
dfs(, );
printf("%d\n", ans);
}
return ;
} void dfs(int row, int count) // row为将要放置棋子的行数,count为已经放置的棋子数
{
if(count == k)
{
ans++;
return;
}
if(row > n || k-count > n-row+) // 定界剪枝
return;
for(int col = ; col <= n; col++)
{
if(map[row][col] == '#' && !vis[col])
{
vis[col] = ; // 1表示当前列已占据
dfs(row+, count+);
vis[col] = ; // 取消标志
}
} dfs(row+, count);
}

OpenJudge_1321:棋盘问题的更多相关文章

  1. TYVJ1035 棋盘覆盖

    时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 给出一张n*n(n<=100)的国际象棋棋盘,其中被删除了一些点,问可以使用多少1*2的多米诺骨牌进行掩 ...

  2. POJ 1321 棋盘问题(dfs)

    传送门 棋盘问题 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 38297   Accepted: 18761 Descri ...

  3. 设计一个自动生成棋盘格子的JS小程序

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. BZOJ1057[ZJOI2007]棋盘制作 [单调栈]

    题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳. 而我们的 ...

  5. 【BZOJ-3039&1057】玉蟾宫&棋盘制作 悬线法

    3039: 玉蟾宫 Time Limit: 2 Sec  Memory Limit: 128 MBSubmit: 753  Solved: 444[Submit][Status][Discuss] D ...

  6. 【ZJOI2007】棋盘制作 BZOJ1057

    Description 国 际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方 阵,对应八八六十四卦,黑白对 ...

  7. Unity手撸2048小游戏——自动生成4*4棋盘

    1.新建文件夹,命prefabs,将刚刚做成的Chessman拖入该文件下,做成预制体 2.删除panel下的Chessman 3.在panel下,新建一个空对象,命名为Chessboard,大小设置 ...

  8. C# 围棋盘的画法

    C#绘图不是那么美,不过对于简单的图形,不注重美感的图质,用C#还是很方便的. 背景颜色.绘制图表线色.纵横列大小可按照个人喜好调节. 不提供AI代码,我自己设计的AI不是很完美,就不拿出来献丑了,算 ...

  9. 炮(棋盘DP)

    一直以为自己写的就是状态压缩,结果写完才知道是个棋盘dp 首先看一下题目 嗯,象棋 ,还是只有炮的象棋 对于方案数有几种,我第一个考虑是dfs,但是超时稳稳的,所以果断放弃 然后记得以前有过和这个题差 ...

随机推荐

  1. C++语法细节笔记

    1.数据类型转换 当赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数. 把负数转换成无符号数类似于直接给无符号数赋一个负值,结果等于这个负数加上无符号数后的模. ...

  2. eclipse没有联想功能的解决办法

    1.我window->Preferences->Java->Editor->content assist 把 Enable auto activation 选项打上勾 :(如下 ...

  3. 从送外卖到建站售主机还有共享自行车说起-2017年8月江西IDC排行榜与发展报告

    曾几何时,送外卖,这样的"低技术含量"工作,很难被互联网公司看上,直到百度将其当作连接终端用户与大数据的管道. 同样,销售主机域名和建站业务,本也是"微小体量" ...

  4. 最近见到的JS返回函数的一些题

    JS返回值题一直都是考察重点,面试和笔试之中也经常涉及到,说一说我最近遇到的一些有意思的JS返回函数问题. 之前见到过一道有意思的问题,说有一个sum函数,用户可以通过sum(2,3)来取到2+3 = ...

  5. python 求解线性方程组

    Python线性方程组求解 求解线性方程组比较简单,只需要用到一个函数(scipy.linalg.solve)就可以了.比如我们要求以下方程的解,这是一个非齐次线性方程组: 3x_1 + x_2 - ...

  6. poj 3013 SPFA

    首先看题看的很懵.. 然后这题直接没想用Djstra做 TLE了.看discuss,Dijstra要用堆优化,也可以用SPFA做. 这里在网上找了这两种做法的区别,点多稠密图用Dij,以为它是操作点的 ...

  7. 转:【Java并发编程】之十九:并发新特性—Executor框架与线程池(含代码)

      Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.coc ...

  8. 设计模式-单体模式(C++)

    设计模式-单体模式 单体模式在使用非常方便,适合于单一的对象,例如全局对象的抽象使用. 需要注意的是单体模式不可继承 // 实现 Singleton.h #ifndef __SINGLETON_H__ ...

  9. 【Beta阶段】测试与发布

    [Beta阶段]测试报告 一.Bug记录 1. 已经修复的BUG:文件查重的小组的空指针处理了 . 2.未能修复的bug: (1).在进行查重的时候必要要有10个文件,不然会报错:        (2 ...

  10. 201521123048 《Java程序设计》第8周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 2. 书面作业 本次作业题集集合 1.List中指定元素的删除(题目4-1) 1.1 实验总结 for (in ...