题目描述

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

    JAVA中的List接口存放的元素是可以重复的,在这个我重写对象里面的equals()方法,让集合里存放的对象不能重复 首先建一个类,在里面的main()方法中实现 list1中存放的是可以重复对象的 ...

  2. 将位图导入为ArcGIS面要素

    本文根据笔者经验,介绍一种从位图图像导入ArcGIS称为要素的方法.这种方法适用于从现有出版物图片中获取地理信息的情况. 首先要说明的是,从位图导入要素是非常非常不精确的方式,如果有其它数据来源,那么 ...

  3. Java 高级特性: Lambda 表达式

    本文源代码上传到了码云,请点击 LambdaExpression 获取.Lambda 表达式是 java 8 的新特性,本文讲解了 lambda 表达式的所有知识.内容涉及到 lambda 表达式是什 ...

  4. 读redux有感: redux原来是这样操作的。

    2017.9.10日 教师节 : ~当一个事物你没有接触,但是生活中 常常用到他,你就不得不去了解他了. 注:新手可以看一下,毕竟博主也是个菜鸟,没法写高深的东西,不想看博主扯淡的直接看第三节啦~~ ...

  5. ADO.NET中SQL Server数据库连接池

    连接到数据库服务器通常由几个需要很长时间的步骤组成. 必须建立物理通道(例如套接字或命名管道),必须与服务器进行初次握手,必须分析连接字符串信息,必须由服务器对连接进行身份验证,必须运行检查以便在当前 ...

  6. startsWith和endWith方法

    startsWith(): 例如:if(a.startsWith(b)) //判断字符串a 是不是以字符串b开头. 语法1 public boolean startsWith(String prefi ...

  7. springboot 入门二- 读取配置信息一

    在上篇入门中简单介绍下springboot启动使用了大量的默认配置,在实际开发过程中,经常需要启动多个服务,那端口如何手动修改呢? 此篇就是简单介绍相关的配置文件信息. Spring Boot允许外部 ...

  8. 轻谈 return i++

    在写函数的时候,发现了又一个很有意思的事情 先上代码 public class Test{ static int number = 2; public static void main(String ...

  9. 201521123084 《Java程序设计》第6周学习总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰,内容覆盖 ...

  10. 第二次项目冲刺(Beta阶段)5.25

    1.提供当天站立式会议照片一张 会议内容: ①检查前一天的任务情况. ②制定新一轮的任务计划. ③对这几日的冲刺进行总结. 2.每个人的工作 (1)工作安排 队员 今日进展 明日安排 王婧 #63(完 ...