1216:红与黑
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 40665 通过数: 16737
【题目描述】
有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。你站在其中一块黑色的瓷砖上,只能向相邻的黑色瓷砖移动。请写一个程序,计算你总共能够到达多少块黑色的瓷砖。
【输入】
包括多组数据。每组数据的第一行是两个整数W和H,分别表示x方向和y方向瓷砖的数量。W和H都不超过20。在接下来的H行中,每行包括W个字符。每个字符表示一块瓷砖的颜色,规则如下:
1)‘.’:黑色的瓷砖;
2)‘#’:红色的瓷砖;
3)‘@’:黑色的瓷砖,并且你站在这块瓷砖上。该字符在每组数据中唯一出现一次。
当在一行中读入的是两个零时,表示输入结束。
【输出】
对每组数据,分别输出一行,显示你从初始位置出发能到达的瓷砖数(记数时包括初始位置的瓷砖)。
【输入样例】
6 9 ....#. .....# ...... ...... ...... ...... ...... #@...# .#..#. 0 0
【输出样例】
45
【代码示例】
#include<iostream>
using namespace std;
char a[21][21];
int d[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int n, m, x1, y1, count;
void dfs(int x, int y){
for(int i = 0; i < 4; i++){
int xx = x + d[i][0];
int yy = y + d[i][1];
if(xx >= 1 && xx <= n && yy >= 1 && yy <= m && a[xx][yy] == '.'){
count++;
a[xx][yy] = '#';
dfs(xx, yy);
}
}
}
int main(){
cin >> m >> n;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
cin >> a[i][j];
if(a[i][j] == '@'){
x1 = i;
y1 = j;
}
}
}
count++;
dfs(x1, y1);
cout << count << endl;
return 0;
}
1213:8皇后问题
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 44790 通过数: 16952
【题目描述】
在国际象棋棋盘上放置8
个皇后,要求每两个皇后之间不能直接吃掉对方。
【输入】
(无)
【输出】
按给定顺序和格式输出所有八皇后问题的解(见样例)。
【输入样例】
(无)
【输出样例】
No. 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 No. 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 ...以下省略
【代码】
#include <iostream>
using namespace std;
int a[9], v1[101], v2[101], v3[101], cnt;//a[i]表示第 i 行的皇后在第几列上
// v1[i]表示第 i 列有没有皇后(有为 1,无为 0)
// v2[x - y + 8]表示坐标为 (x, y) 的点所在的右斜线(\)有没有皇后(有为 1,无为 0)
// v3[x + y]表示坐标为 (x, y) 的点所在的左斜线(/)有没有皇后(有为 1,无为 0)
void dfs(int x) {
if(x > 8) {//八个皇后放完了,输出
cout << "No." << ++cnt << endl;
printf("No. %d\n", ++cnt);
for(int i = 1; i < 9; ++i) {
for(int j = 1; j < 9; ++j) {
if(a[j] == i){
cout << "1 " << endl;
}else{
cout << "0 " << endl;
}
}
puts("");
}
} else {
for(int i = 1; i < 9; ++i) {
if(!v1[i] && !v2[x - i + 8] && !v3[x + i]) {
// 坐标为 (x, i) 的点没有被其他皇后占领,此点可以放皇后
a[x] = i;// 第 x 行的皇后放在了第 i 列
v1[i] = 1;// 占领列
v2[x - i + 8] = 1;// 占领右斜线
v3[x + i] = 1;// 占领左斜线
dfs(x + 1);// 在下一行放皇后
v1[i] = 0;// 回溯
v2[x - i + 8] = 0;
v3[x + i] = 0;
}
}
}
}
int main() {
dfs(1);// 从第一行开始放
return 0;
}
1219:马走日
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 29872 通过数: 15673
【题目描述】
马在中国象棋以日字形规则移动。
请编写一段程序,给定n×m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点。
【输入】
第一行为整数T(T < 10),表示测试数据组数。
每一组测试数据包含一行,为四个整数,分别为棋盘的大小以及初始位置坐标n,m,x,y。(0≤x≤n-1,0≤y≤m-1, m < 10, n < 10)。
【输出】
每组测试数据包含一行,为一个整数,表示马能遍历棋盘的途径总数,0为无法遍历一次。
【输入样例】
1 5 4 0 0
【输出样例】
32
【代码示例】
#include<bits/stdc++.h>
using namespace std;
int a[100][100];
int fx[9] = {0, -1, 1, 2, 2, 1, -1, -2, -2};
int fy[9] = {0, 2, 2, 1, -1, -2, -2, -1, 1};
int n, m, x, y, cnt = 0;
void dfs(int x, int y, int sum){
if(sum == n * m){ //表明所有格子已走完
cnt++;
return;
}else{
for(int i = 1; i <= 8; i++){//遍历8个方向
int xx = x + fx[i], yy = y + fy[i];
if(xx >= 0 && xx < n && yy >= 0 && yy < m && a[xx][yy] == 0){
//待探索的格子是否合法
a[x][y] = 1; //当前的格子先标记为已遍历
dfs(xx, yy, sum + 1);
a[x][y] = 0; //遍历结束,回退的格子状态还原,回溯
}
}
}
}
int main(){
int t;
cin >> t;
while(t--){//读入t组测试数据
cin >> n >> m >> x >> y;//读入数据
dfs(x, y, 1);
cout << cnt << endl;
cnt = 0; //本轮计算结束,结果归零等待下一次统计
}
return 0;
}
1215:迷宫
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 67224 通过数: 21717
【题目描述】
一天Extense在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由n×n
的格点组成,每个格点只有2
种状态,.
和#
,前者表示可以通行后者表示不能通行。同时当Extense处在某个格点时,他只能移动到东南西北(或者说上下左右)四个方向之一的相邻格点上,Extense想要从点A走到点B,问在不走出迷宫的情况下能不能办到。如果起点或者终点有一个不能通行(为#
),则看成无法办到。
【输入】
第1行是测试数据的组数k
,后面跟着k组输入。每组测试数据的第1行是一个正整数n(1≤n≤100),表示迷宫的规模是n×n的。接下来是一个n×n的矩阵,矩阵中的元素为.
或者#
。再接下来一行是4个整数ha,la,hb,lb,描述A处在第ha行, 第la列,B处在第hb行, 第lb列。注意到ha,la,hb,lb全部是从0
开始计数的。
【输出】
k
行,每行输出对应一个输入。能办到则输出“YES”,否则输出“NO”。
【输入样例】
2 3 .## ..# #.. 0 0 2 2 5 ..... ###.# ..#.. ###.. ...#. 0 0 4 0
【输出样例】
YES NO
【代码示例】
#include <bits/stdc++.h>
using namespace std;
#define N 105
int n, ha, la, hb, lb;
char mp[1001][1001];
bool vis[1001][1001];
int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
bool flag;
void dfs(int x, int y){
if(flag){//剪枝:如果发现已经能到了,就不再递归运行了
return;
}
for(int i = 0; i < 4; i++){
int xx = x + dir[i][0], yy = y + dir[i][1];
if(xx >= 0 && xx < n && yy >= 0 && yy < n && vis[xx][yy] == false &&
mp[xx][yy] == '.'){
vis[x][y] = true;
if(xx == hb && yy == lb){
flag = true;
return;
}else{
dfs(xx, yy);
}
}
}
}
int main(){//判断起点终点是否在一个连通块内
int k;
cin >> k;
while(k--){
cin >> n;
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
cin >> mp[i][j];
}
}
cin >> ha >> la >> hb >> lb;
memset(vis, 0, sizeof(vis));
flag = false;
vis[ha][la] = true;
if(ha == hb && la == lb){//如果起点和终点重合,直接就能到达
flag = true;
}
if(mp[ha][la] != '#' && mp[hb][lb] != '#'){
dfs(ha, la);
}
if(flag){
cout << "YES" << endl;
} else {
cout << "NO" << endl;
}
}
return 0;
}