棋盘问题
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 60815 | Accepted: 29135 |
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
思路:典型回溯水题,不过这一次学到了不存小地图方法,就是每次存棋盘的位置就行了。而且这个样子的话,相当于给每个位置标好了号码,这样就可以吧问题转变成组合问题,我们拿个栗子说明
输入样例: 3 2 #.. .#. ..# -1 -1 输出样例: 3
很明显的1,2,3,然后从中选两个,方式就是1先找后面能满足条件的,有1和2、1和3;然后从2往后找,有2和3;然后从3往后找,结束。
注意:提交的时候WA了,试试换个提交方式!!!随便放一段毒代码
#include <iostream> #include <cstdio> #include <string> #include <string.h> #define ll long long using namespace std; int pa[100], pb[100]; //棋盘摆放 #棋盘区域 .空白区域 int n, k; //表明是n*n的矩阵 摆放k个棋子 int vx[100] = { 0 }; //走过的行的位置 int vy[100] = { 0 }; //走过的列的位置 ll sum = 0; //摆放的方法 int ss; //记录#的个数 int visit[1000] = { 0 }; //走过的点 void dfs(int i, int j){ if (j == k){ sum++; } else{ for (int l = i; l<ss; ++l){ if (visit[l] == 0 && vx[pa[l]] == 0 && vy[pb[l]] == 0){ vx[pa[l]] = 1; vy[pb[l]] = 1; visit[l] = 1; dfs(l + 1, j + 1); vx[pa[l]] = 0; vy[pb[l]] = 0; visit[l] = 0; } } } } int main() { ios::sync_with_stdio(false); while (~scanf("%d%d",&n,&k)) { getchar(); if (n == -1 && k == -1)break; sum = 0; ss = 0; memset(vx, 0, sizeof(vx)); memset(vy, 0, sizeof(vy)); memset(visit, 0, sizeof(visit)); for (int i = 0; i<n; ++i){ for (int j = 0; j<n; ++j){ char temp; cin >> temp; if (temp == '#'){ pa[ss] = i; //把棋盘区域(i,j)加进数组 pb[ss++] = j; } } } dfs(0, 0); //从第一个为#的点开始,一开始摆放的棋子数为0; cout << sum << endl; } return 0; }
以下AC代码:
#include<iostream> #include<string.h> using namespace std; int n, k, sum, len; int pa[100], pb[100], vx[10] = { 0 }, vy[10] = { 0 }, vis[100] = { 0 }; void dfs(int s, int c) { if (c > k)return; if (c == k)sum++; else { for (int i = s; i < len;i++) if (vis[i] == 0 && vx[pa[i]] == 0 && vy[pb[i]] == 0){ vis[i] = vx[pa[i]] = vy[pb[i]] = 1; dfs(i + 1, c + 1); vis[i] = vx[pa[i]] = vy[pb[i]] = 0; } } } int main() { ios::sync_with_stdio(false); while (cin >> n >> k, n != -1 && k != -1){ len = sum = 0; for (int i = 0; i < n;i++) for (int j = 0; j < n; j++){ char ch; cin >> ch; if (ch == '#'){ pa[len] = i; pb[len++] = j; } } dfs(0, 0); cout << sum << endl; } return 0; }