题目描述

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

    兔子问题(斐波那契数列规律) 台阶问题 (兔子问题变种,递归规律) 素数问题(判断素数.质数方式) 水仙花数问题(数字分解) 查找算法(二分查找) 排序算法(选择排序,冒泡排序,快速排序) 兔子问题, ...

  2. 利用JavaScript来切换样式表

    切换样式表 html页 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:/ ...

  3. css 找到隐藏元素个数

    <form>   <input type="hidden" name="email" />   <input type=" ...

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

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

  5. mqtt实现自动监听服务器消息

    本示例借助meteor的一个环境跑,和我们平时用的node自己搭的环境或java,php的环境本质一样,在此不多讨论. 首先需求是:多系统对接进行消息实时传递. 安装好mqtt:  npm insta ...

  6. SVN服务器搭建(一)

    本教程以64位win10系统为例在本地搭建svn服务器,安装完成后,即可访问本地svn服务器上的项目,也可以访问网上其他svn服务器上的项目. 一.首先准备三个软件: 1.VisualSVN-Serv ...

  7. 使用github出了些问题?fatal: unable to access;Failed connect to github.com:8087;

    使用github出了些问题?fatal: unable to access;Failed connect to github.com:8087; No error 我今天使用git push orig ...

  8. SNS团队第四次站立会议(2017.04.25)

    一.当天站立式会议照片 本次会议主要内容:汇报工作进度,根据完成情况调整进度 二.每个人的工作 成员 今天已完成的工作 明天计划完成的工作 罗于婕 相关数据库文件建立起来  完善数据库文件 龚晓婷 研 ...

  9. JAVA课程设计个人博客 学生成绩管理 201521123014 黄绍桦

    1. 团队课程设计博客链接 http://www.cnblogs.com/kawajiang/p/7062407.html 2.个人负责模块或任务说明 本人主要负责DAO模式.添加和修改学生的信息功能 ...

  10. PHP面向对象三大特性之一:封装

    面向对象的三大特性:封装.继承.多态 1.封装 封装的目的:让类更加安全,做法是不让外界直接访问类的成员 具体做法:1.成员变为私有:访问修饰符(public.private.protected)   ...