棋盘问题

Time Limit: 1000MS Memory Limit: 10000K

Total Submissions: 62164 Accepted: 29754

Description

在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。

Input

输入含有多组测试数据。

每组数据的第一行是两个正整数,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

Source

蔡错@pku

【分析】:因为棋子的数量k比棋盘数目n少,那么可能有些棋盘区不用放置棋子。这是重点,易错点。

然后这道题和n皇后有点像,要求同一行、同一列不能放棋子,那么我们一行到下一行逐行搜索,是自然遍历下来的,不用管;就用一个数组标记列放没放棋子,没放过并且是棋盘区就标记可以放,然后回溯(还原现场)进行下一次尝试。

这里有两种情况,由于只要放k个棋子,且有些行不能放棋子。处理当前行的时候有两种状态,一是在当前行放棋子,二是不放棋子。放棋子就判断是否有相同列,不放棋子则直接深搜下一行。

而dfs的办法也有几种,常见的有

1.参数只有一个i表示当前搜索行;

2.参数有i表示当前搜索行和cnt表示已填充的棋子数 ;

3.参数有i表示当前搜索行和cnt表示已填充的棋子数 ,双重循环遍历,不用考虑放不放

【代码】:

#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<cctype>
#include<stack>
#include<sstream>
#include<list>
#include<assert.h>
#include<bitset>
#include<numeric>
#define debug() puts("++++")
#define gcd(a,b) __gcd(a,b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a,b,sizeof(a))
#define sz size()
#define be begin()
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
#define all 1,n,1
#define rep(i,n,x) for(int i=(x); i<(n); i++)
#define in freopen("in.in","r",stdin)
#define out freopen("out.out","w",stdout)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e18;
const int maxn = 1e6;
const int maxm = 10;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int dx[] = {-1,1,0,0,1,1,-1,-1};
const int dy[] = {0,0,1,-1,1,-1,1,-1};
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int n,k;
char a[maxm][maxm],v[maxm];
int cnt,tot; void dfs(int i)
{
if(cnt==k) //当计数器达到k(摆放棋子的数目),不管结果如何都结束了
{
tot++;
return ;
}
if(i>=n) return ;
for(int j=0;j<n;j++)
{
if(!v[j] && a[i][j]=='#')
{
v[j]=1;
cnt++;
dfs(i+1);
v[j]=0;
cnt--;
}
}
dfs(i+1); //i行不放棋子
} int main()
{
while(~scanf("%d%d",&n,&k))
{
tot=cnt=0;
ms(a,0);
if(n==-1&&k==-1) break;
getchar(); // for(int i=0;i<n;i++)
gets(a[i]); dfs(0);
cout<<tot<<endl;
}
}
/*
2 1
#.
.#
4 4
...#
..#.
.#..
#...
*/

POJ 1321 棋盘问题【DFS/回溯/放与不放/类似n皇后】的更多相关文章

  1. POJ 1321 棋盘问题 (DFS + 回溯)

    题目链接:http://poj.org/problem?id=1321 题意:中文题目,就不多说了...... 思路: 解题方法挺多,刚开始想的是先从N行中选择出来含有“#”的K行,再在这K行中放置K ...

  2. POJ 1321 棋盘问题 --- DFS

    POJ 1321 题目大意:给定一棋盘,在其棋盘区域放置棋子,需保证每行每列都只有一颗棋子. (注意 .不可放 #可放) 解题思路:利用DFS,从第一行开始依次往下遍历,列是否已经放置棋子用一个数组标 ...

  3. POJ - 1321 棋盘问题 dfs分层搜索(n皇后变式)

    棋盘问题 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 47960   Accepted: 23210 Descriptio ...

  4. poj 1321 棋盘问题 (回溯法)

    棋盘问题 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 69951   Accepted: 33143 Descriptio ...

  5. POJ 1321 棋盘问题(DFS板子题,简单搜索练习)

    棋盘问题 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 44012   Accepted: 21375 Descriptio ...

  6. Poj 1321 棋盘问题 【回溯、类N皇后】

    id=1321" target="_blank">棋盘问题 Time Limit: 1000MS   Memory Limit: 10000K Total Subm ...

  7. POJ 1321 棋盘问题 dfs 难度:0

    http://poj.org/problem?id=1321 注意是在'#'的地方放棋子 矩阵大小不过8*8,即使是8!的时间复杂度也足以承受,可以直接dfs求解 dfs时标注当前点的行和列已被访问, ...

  8. (简单) POJ 1321 棋盘问题,回溯。

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

  9. POJ 1321 棋盘问题 DFS搜索

    简单搜索 练习一下回溯 #include <iostream> #include <cstdio> #include <cstring> #include < ...

  10. POJ 1321 棋盘问题 DFS 期末前水一水就好……

    A - 棋盘问题 Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Sta ...

随机推荐

  1. 使用JSON数据格式模拟股票实时信息

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

  2. 解决IIS的Server Application Error

    问题描述一下: Server Application ErrorThe server has encountered an error while loading an application dur ...

  3. TCP/IP Note2

    TCP/IP寻址 TCP/IP使用32个比特或者4个0到255之间的数字来为计算机编址. 1. IP地址 每个计算机必须有一个IP地址才能够连入Internet中. 每个IP包必须有一个地址才能够发送 ...

  4. 【CF edu 30 D. Merge Sort】

    time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standa ...

  5. 【BZOJ 1492】 [NOI2007]货币兑换Cash 斜率优化DP

    先说一下斜率优化:这是一种经典的dp优化,是OI中利用数形结合的思想解决问题的典范,通常用于优化dp,有时候其他的一些决策优化也会用到,看待他的角度一般有两种,但均将决策看为二维坐标系上的点,并转化为 ...

  6. 【BZOJ】2453: 维护队列【BZOJ】2120: 数颜色 二分+分块(暴力能A)

    先说正解:把所有相同的数相成一个链在每一个区间里的种数就是不同链的链头,那么记录每个数的上个相同数所在位置,那么只要找出l到r之间前驱值在l之前的数的个数就可以了 本人打的暴力,有一个小技巧,用cha ...

  7. 用boost::lexical_cast进行数值转换

    在STL库中,我们可以通过stringstream来实现字符串和数字间的转换: int i = 0;    stringstream ss; ss << "123";  ...

  8. codeforces 1060 B

    https://codeforces.com/contest/1060/problem/B 题意:给你一个数C ,你要找到两个数A.B,使得A+B=C并且A的每个位的数的和最大,求最大的和是多少 题解 ...

  9. Linux命令的返回值

    转摘自:http://hi.baidu.com/suchshow/item/230255b6caab369218469732 在 Linux 下,不管你是启动一个桌面程序也好,还是在控制台下运行命令, ...

  10. 动态规划:LCS

    先上状态转移方程,还是很容易看明白的 例题是Codevs的1862,这个题不是实现了方程就可以了的,还要完成一个事情那就是计数,数一数到底有多少个最长公共子序列 #include<cstdio& ...