- 搜索
- 棋盘问题
- 地牢大师
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。
要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放 k 个棋子的所有可行的摆放方案数目 C C C。
输入格式
输入含有多组测试数据。
每组数据的第一行是两个正整数 n n n, k k k,用一个空格隔开,表示了将在一个 n ∗ n n∗n n∗n 的矩阵内描述棋盘,以及摆放棋子的数目。当为 − 1 -1 −1 − 1 -1 −1时表示输入结束。
随后的 n n n 行描述了棋盘的形状:每行有 n n n 个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
输出格式
对于每一组数据,给出一行输出,输出摆放的方案数目
C
C
C (数据保证
C
<
231
C<231
C<231)。
数据范围
n
≤
8
n≤8
n≤8,
k
≤
n
k≤n
k≤n
输入样例:
2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1
输出样例:
2
1
Code:
#include
using namespace std;
typedef long long LL;
const int N = 10;
char map[N][N]; // 存放地图
bool col[N]; // 如果所在列有棋子为 true ,没有棋子为 false
int n, k;
LL cnt;
void dfs(int u, int s) // 逐行枚举
{
if(s == k) // 当放够了 k 个棋子,方案数加一后返回
{
cnt++;
return;
}
if(u == n) return; // 越界
// 不放
dfs(u + 1, s);
// 放
for(int i = 0; i < n; i++)
{
if(!col[i] && map[u][i] == '#')
{
col[i] = true; // 该列置为真,不能再放棋子
dfs(u + 1, s + 1);
col[i] = false; // 恢复现场
}
}
}
int main()
{
while(cin >> n >> k, n != -1 && k != -1)
{
cnt = 0; // 注意每组数据开始前都要初始化 cnt
for (int i = 0; i < n; i ++)
for (int j = 0; j < n; j ++) cin >> map[i][j];
dfs(0, 0);
cout << cnt << endl;
}
return 0;
}
地牢大师
你现在被困在一个三维地牢中,需要找到最快脱离的出路!
地牢由若干个单位立方体组成,其中部分不含岩石障碍可以直接通过,部分包含岩石障碍无法通过。
向北,向南,向东,向西,向上或向下移动一个单元距离均需要一分钟。
你不能沿对角线移动,迷宫边界都是坚硬的岩石,你不能走出边界范围。
请问,你有可能逃脱吗?
如果可以,需要多长时间?
输入格式
输入包含多组测试数据。
每组数据第一行包含三个整数 L L L, R R R, C C C 分别表示地牢层数,以及每一层地牢的行数和列数。
接下来是 L L L 个 R R R 行 C C C 列的字符矩阵,用来表示每一层地牢的具体状况。
每个字符用来描述一个地牢单元的具体状况。
其中, 充满岩石障碍的单元格用”#”表示,不含障碍的空单元格用”.”表示,你的起始位置用”S”表示,终点用”E”表示。
每一个字符矩阵后面都会包含一个空行。
当输入一行为”0 0 0”时,表示输入终止。
输出格式
每组数据输出一个结果,每个结果占一行。
如果能够逃脱地牢,则输出”Escaped in x minute(s).”,其中X为逃脱所需最短时间。
如果不能逃脱地牢,则输出”Trapped!”。
数据范围
1
≤
L
1≤L
1≤L,
R
R
R,
C
≤
100
C≤100
C≤100
输入样例:
3 4 5
S....
.###.
.##..
###.#
#####
#####
##.##
##...
#####
#####
#.###
####E
1 3 3
S##
#E#
###
0 0 0
输出样例:
Escaped in 11 minute(s).
Trapped!
Code:
#include
#include
#include
using namespace std;
const int N = 110;
struct Point
{
int x, y, z;
};
int l, r, c;
char map[N][N][N];
Point q[N * N * N];
int dist[N][N][N];
int dx[] = {0, 1, 0, -1, 0, 0}, dy[] = {1, 0, -1, 0, 0, 0}, dz[] = {0, 0, 0, 0, 1, -1};
int bfs(Point start, Point end)
{
int hh = 0, tt = 0;
q[0] = start; // 把起点作为队头
memset(dist, -1, sizeof(dist)); // 初始化为 -1
dist[start.x][start.y][start.z] = 0;
while(hh <= tt)
{
auto t = q[hh++]; // 取
for (int i = 0; i < 6; i++)
{
int x = t.x + dx[i], y = t.y + dy[i], z = t.z + dz[i]; // (x, y, z) 为下一步的位置
if(x < 0 || x >= l || y < 0 || y >= r || z < 0 || z >= c) continue; // 越界
if(map[x][y][z] == '#') continue; // 障碍物
if(dist[x][y][z] != -1) continue; // 如果不为 -1, 说明之前走过这里
dist[x][y][z] = dist[t.x][t.y][t.z] + 1; // 合法,距离加 1
if(x == end.x && y == end.y && z == end.z) return dist[x][y][z]; // 如果到达终点,返回此时的距离
q[++tt] = {x, y, z}; // 插
}
}
return -1; // 没有到达, 返回 -1
}
int main()
{
while(scanf("%d%d%d", &l, &r, &c), l || r || c)
{
Point start, end; // 起点和终点
int flag = 0;
for(int i = 0; i < l; i++)
{
for(int j = 0; j < r; j++)
{
scanf("%s", map[i][j]);
for(int k = 0; k < c; k++)
{
char c = map[i][j][k];
if(c == 'S') start = {i, j, k}, flag++;
else if(c == 'E') end = {i, j, k}, flag++;
if(flag == 2) break;
}
}
}
int distance = bfs(start, end);
if(distance == -1) puts("Trapped!");
else printf("Escaped in %d minute(s).\n", distance);
}
return 0;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)