小M最近爱上了扫雷游戏,就是在一个n*m的区域中,有地雷,每一个方格上都有一个数字s,表示在这个方格周围有s颗雷,现在给你一张表明地雷的图,并且指定一个位置点开,请输出点开后的数字情况,若点开的地方的数字为0,则向该方格周围扩展,直到遇到数字或者地图边界为止,若点开的地方为地雷,那么直接输出"GG"。
周围指的是上,左上,左,左下,下,右下,右,右上八个方向。
小M最近爱上了扫雷游戏,就是在一个n*m的区域中,有地雷,每一个方格上都有一个数字s,表示在这个方格周围有s颗雷,现在给你一张表明地雷的图,并且指定一个位置点开,请输出点开后的数字情况,若点开的地方的数字为0,则向该方格周围扩展,直到遇到数字或者地图边界为止,若点开的地方为地雷,那么直接输出"GG"。
周围指的是上,左上,左,左下,下,右下,右,右上八个方向。
第一行有两个数字n和m(2<=n,m<=1000),表示地图的大小,第二行有两个整数x和y(1<=x<=n,1<=y<=m),表示点击第x行y列的方格,接下来的是一个n行m列的一个矩阵,表示地图,其中.表示空地,*表示地雷。
如果点开的地方为地雷直接输出"GG"。否则输出点击指定位置后的地图,"."表示未点开的空地,"*"表示地雷,数字表示在该方格周围的地雷数目。
3 4 1 1 .... ..*. ....
01.. 01*. 01..
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <string.h> #include <errno.h> #define N 1001 #define OK 1 #define ERROR -1 #define MEM_OVERFLOW -2 #define not ! typedef int Status; // 两维平面的纵横坐标系 typedef struct Coordintate { int x; int y; } Coord; // =============== 循环队列的存储结构表示与实现 =============== typedef Coord QElemType; typedef struct { QElemType* base; int front; int rear; int capacity; } SqQueue; Status InitQueue(SqQueue* Q, int capacity) { if (capacity < 1) { printf("InitQueue ERROR: The capacity %d Must be > 0!", capacity); return ERROR; } if (!(Q->base = (QElemType*) malloc((capacity + 1) * sizeof(QElemType)))) { printf("InitQueue Memory Overflow: %s\n", strerror(errno)); exit(MEM_OVERFLOW); } Q->front = Q->rear = 0; Q->capacity = capacity + 1; return OK; } bool QueueEmpty(SqQueue* Q) { return Q->front == Q->rear; } bool QueueFull(SqQueue* Q) { return (Q->rear + 1) % Q->capacity == Q->front; } size_t QueueLength(SqQueue* Q) { return (Q->rear - Q->front + Q->capacity) % Q->capacity; } Status EnQueue(SqQueue* Q, QElemType e) { if (QueueFull(Q)) { puts("EnQueue ERROR: The queue is full!"); return ERROR; } Q->rear = (Q->rear + 1) % Q->capacity; *(Q->base + Q->rear) = e; return OK; } Status DeQueue(SqQueue* Q, QElemType* ret) { if (QueueEmpty(Q)) { puts("DeQueue ERROR: The queue is empty!"); return ERROR; } Q->front = (Q->front + 1) % Q->capacity; *ret = *(Q->base + Q->front); return OK; } Status DestroyQueue(SqQueue* Q) { free(Q->base); return OK; } // =============== 循环队列的存储结构表示与实现 =============== // =============== The global variable area =============== char board[N][N]; int visited[N][N]; int m, n, sx, sy; // =============== The global variable area =============== // =============== function declaration =============== /** 初始化棋盘 */ void initBoard(void); /** 广度优先搜索算法 */ void breadth_first_search_algorithm(); /** 在电脑屏幕上打印扫雷棋盘 */ void printBoard(void); // =============== function declaration =============== int main(const int argc, const char** argv) { initBoard(); // corner case if (board[sy][sx] == '*') return puts("GG"), 0; // GAME OVER == GG // two solutions breadth_first_search_algorithm(); // depth_first_search_algorithm(); printBoard(); return 0; } void initBoard(void) { int x, y; scanf("%d%d", &m, &n); scanf("%d%d", &sy, &sx); getchar(); for (y = 1; y <= m; ++y) { for (x = 1; x <= n; ++x) scanf("%c", &board[y][x]); getchar(); } memset(visited, 0x0000, sizeof visited); } void breadth_first_search_algorithm(void) { SqQueue Q; InitQueue(&Q, 2000); EnQueue(&Q, (Coord) {.x = sx, .y = sy}); visited[sy][sx] = 1; // mark as visited Coord coord; int x, y, r, c, cnt; while (not QueueEmpty(&Q)) { DeQueue(&Q, &coord); x = coord.x, y = coord.y; cnt = 0; // 当前坐标四周8个方向的**数量 for (r = fmax(1, y - 1); r <= fmin(m, y + 1); ++r) for (c = fmax(1, x - 1); c <= fmin(n, x + 1); ++c) cnt += board[r][c] == '*'; board[y][x] = cnt + 48; if (cnt) continue; for (r = fmax(1, y - 1); r <= fmin(m, y + 1); ++r) for (c = fmax(1, x - 1); c <= fmin(n, x + 1); ++c) { if (visited[r][c]) continue; EnQueue(&Q, (Coord) {.x = c, .y = r}); visited[r][c] = 1; // mark as viisted } } DestroyQueue(&Q); } void printBoard(void) { int x, y; for (y = 1; y <= m; ++y) { for (x = 1; x <= n; ++x) printf("%c", board[y][x]); putchar('\n'); } }
/*
连通图的遍历
*/
#include <bits/stdc++.h>
using namespace std;
#define N 1002
int n, m, x, y;
int dx[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
int dy[8] = {0, -1, -1, -1, 0, 1, 1, 1};
char a[N][N];
bool display[N][N], vis[N][N];
void count()
{
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(a[i][j] == '*') {
display[i][j] = true;
for(int k = 0; k < 8; k++) {
if(a[i + dx[k]][j + dy[k]] == '*' || a[i + dx[k]][j + dy[k]] == 0) continue;
if(a[i + dx[k]][j + dy[k]] == '.') {
a[i + dx[k]][j + dy[k]] = '1';
} else {
a[i + dx[k]][j + dy[k]]++;
}
}
}
}
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(a[i][j] == '.') {
a[i][j] = '0';
}
}
}
}
void sweep()
{
display[x][y] = true;
if(a[x][y] != '0') return;
queue<pair<int, int>> Q;
Q.push(make_pair(x, y));
vis[x][y] = true;
int i, j;
while(!Q.empty()) {
tie(i, j) = Q.front();
Q.pop();
for(int k = 0; k < 8; k++) {
display[i + dx[k]][j + dy[k]] = true;
if(a[i + dx[k]][j + dy[k]] == '0' && vis[i + dx[k]][j + dy[k]] == false) {
vis[i + dx[k]][j + dy[k]] = true;
Q.push(make_pair(i + dx[k], j + dy[k]));
}
}
}
}
void print()
{
if(a[x][y] == '*') {
printf("GG\n");
return;
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(display[i][j]) {
printf("%c", a[i][j]);
} else {
printf(".");
}
}
cout << endl;
}
}
int main()
{
// freopen("input.txt","r",stdin);
int i, j;
cin >> n >> m >> x >> y;
memset(a, 0, sizeof(a));
memset(display, 0, sizeof(display));
memset(vis, 0, sizeof(vis));
for(i = 1; i <= n; i++) {
getchar();
for(j = 1; j <= m; j++) {
cin >> a[i][j];
}
}
count(); // 统计全图各点周围的雷数
sweep(); // 连通图扫描出显示区域
print(); // 输出显示区域
}
#include <bits/stdc++.h> using namespace std; char G[1002][1002]; int n,m; int dir[8][2] = {{0,-1}, {0,1}, {-1,0}, {1,0}, {-1,-1}, {-1,1}, {1,-1}, {1,1}}; struct P{ int x,y; }; int F(int x, int y){ int cnt = 0; for(int i=x-1;i<=x+1;i++) for(int j=y-1;j<=y+1;j++) if(G[i][j]=='*') cnt++; G[x][y] = '0' + cnt; return cnt; } void BFS(int x, int y){ queue<P> q; q.push(P{x,y}); while(!q.empty()){ P p = q.front(); q.pop(); for(int i=0;i<8;i++){ int xx = p.x + dir[i][0]; int yy = p.y + dir[i][1]; if(xx==0 || xx==n+1 || yy==0 || yy==m+1 || G[xx][yy]!='.') continue; int s = F(xx,yy); if(s==0) q.push(P{xx,yy}); } } return; } int main(){ int x,y; cin>>n>>m>>x>>y; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>G[i][j]; if(G[x][y]=='*') cout<<"GG"<<endl; else{ if(F(x,y)==0) BFS(x,y); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++) cout<<G[i][j]; cout<<endl; } } return 0; }
需要注意的是,输出结果时,最好一次输出,否则很容易超时。 import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc=new Scanner(System.in); while(sc.hasNext()){ int n=sc.nextInt(); int m=sc.nextInt(); int x=sc.nextInt()-1; int y=sc.nextInt()-1; char[][] arr=new char[n][m]; for(int i=0;i<n;i++){ arr[i]=sc.next().toCharArray(); } if(arr[x][y]=='*') { System.out.println("GG"); }else { List<Point> list=new ArrayList<>(); arr[x][y]=getBomb(arr,x,y); list.add(new Point(x,y)); while(list.size()>0) { click(arr,list) ; } StringBuilder sb=new StringBuilder(); for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { sb.append(arr[i][j]); } sb.append("\n"); } System.out.println(sb.toString()); } } sc.close(); } private static void click(char[][] arr,List<Point> list) { Point p=list.remove(0); int x=p.getX(); int y=p.getY(); if(arr[x][y]!='0') return; for(int i=x-1;i<=x+1;i++) { if(i<0||i>=arr.length) continue; for(int j=y-1;j<=y+1;j++) { if(j<0||j>=arr[0].length||(i==x&&j==y)) continue; if(arr[i][j]=='.') { arr[i][j]=getBomb(arr,i,j); list.add(new Point(i,j)); } } } } private static char getBomb(char[][] arr,int x,int y) { int count=0; for(int i=x-1;i<=x+1;i++) { if(i<0||i>=arr.length) continue; for(int j=y-1;j<=y+1;j++) { if(j<0||j>=arr[0].length) continue; if(arr[i][j]=='*') { count++; } } } return Character.forDigit(count, 10); } } class Point{ private int x; private int y; public Point(int x,int y) { this.x=x; this.y=y; } public int getX() { return x; } public int getY() { return y; } }
//注意输出换行符号,这题卡得比较紧 //深度优先搜索没法做,只能用广度 //最后,感谢 @神经咩 提供思路 #include <iostream> #include <string> #include <vector> #include <algorithm> #include <limits.h> #include <queue> using namespace std; vector dx = { -1, -1, -1, 0, 0, 1, 1, 1 }; //y轴方向数组 vector dy = { -1, 0, 1, -1, 1, -1, 0, 1 }; //检查当前位置的周围**的总数 int Count(vector> &vec, int x, int y) { int cnt = 0; int nx = 0, ny = 0; for (int i = 0; i < 8; i++) { nx = x + dx[i]; ny = y + dy[i]; if (vec[nx][ny] == '*') { cnt++; } } vec[x][y] = cnt + '0'; return cnt; } //如果当前位置的**个数为0则向周围搜索,直到遇到超出边界或是遇到数字 void BFS_mineSweeper(vector> &vec, int n, int m, int x, int y) { queue> que; que.push(make_pair(x, y)); pair temp; int cnt = 0; int nx = 0; int ny = 0; //广度优先搜索的目的是查找当前点周围的数是否符合要求,使用队列和迭代比较好理解 while (!que.empty()) { temp = que.front(); que.pop(); for (int i = 0; i < 8; i++) { nx = temp.first + dx[i]; ny = temp.second + dy[i]; //如果越界或是不为点号,则继续搜索 if (nx n || ny m || vec[nx][ny] != '.') { continue; } //统计当前点周围**的数量 cnt = Count(vec, nx, ny); //如果**数量为0则加入待搜索队列 if (cnt == 0) { que.push(make_pair(nx, ny)); } } } } void mineSweeping() { int n, m, x, y; cin >> n >> m >> x >> y; //防止Count() 判断时发生越界,对数组vec进行外部一圈填充 vector> vec(n+2, vector(m+2)); //接收数组值,注意测试数据是从1开始的 for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cin >> vec[i][j]; } } if (vec[x][y] == '*') { cout << "GG" << endl; } else { //当前位置的**个数是否为0 if (Count(vec, x, y) == 0) { BFS_mineSweeper(vec, n, m, x, y); } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cout << vec[i][j]; } cout << endl; } } } int main(){ mineSweeping(); return 0; }
//贴一下我杂乱的代码 #include<iostream> (720)#include<string> #include<vector> (721)#include<queue> using namespace std; int n, m; vector<vector<int>> Dir = { { -1, 0 },{ -1, -1 },{ 0, -1 },{ 1, -1 },{ 1, 0 },{ 1, 1 },{ 0, 1 },{ -1, 1 } }; void BFS(int i1, int j1, vector<vector<char>> &v, vector<vector<int>> &Num, vector<vector<bool>> &vis) { queue<vector<int>> q; q.push(vector<int>{i1, j1}); int row, col; int i, j; while (!q.empty()) { int count = q.size(); for (int k = 0; k < count; k++) { vector<int> temp = q.front(); q.pop(); i = temp[0]; j = temp[1]; vis[i][j] = true; for (int t = 0; t < 8; t++) { row = i + Dir[t][0]; col = j + Dir[t][1]; //cout << "row = " << row << " col = " << col << endl; if (row >= 0 && row < n && col >= 0 && col < m) { //cout << "row = " << row << " col = " << col << endl; //cout << Num[row][col] << endl; if (Num[row][col] > 0) { vis[row][col] = true; } else if (Num[row][col] == 0 && !vis[row][col]) { //cout << "row = " << row << " col = " << col << endl; vis[row][col] = true; q.push(vector<int> {row, col}); } } } } } } void GetNum(vector<vector<char>> &v, vector<vector<int>> &Num) { int row, col; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (v[i][j] != '*') { int count = 0; for (int k = 0; k < 8; k++) { row = Dir[k][0] + i; col = Dir[k][1] + j; if (row >= 0 && row < n && col >= 0 && col < m && v[row][col] == '*') count++; } Num[i][j] = count; } else { Num[i][j] = -1; } } } } void Show(int row, int col, int num, vector<vector<char>> &v) { for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (i == row && j == col) { cout << num; } else { cout << v[i][j]; } } cout << endl; } } void ShowBroad(vector<vector<int>> &Num, vector<vector<bool>> &vis) { for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (Num[i][j] == -1) cout << "*"; else if (vis[i][j]) cout << Num[i][j]; else cout << "."; } cout << endl; } } void ShowNum(vector<vector<int>> Num) { for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cout << Num[i][j]<< " "; } cout << endl; } } int main(void) { cin >> n >> m; int row, col; cin >> row >> col; char c; vector<vector<char>> v(n, vector<char>(m)); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cin >> c; v[i][j] = c; } } vector<vector<int>> Num(n, vector<int>(m)); GetNum(v, Num); //ShowNum(Num); if (v[row - 1][col - 1] == '*') { cout << "GG" << endl; return 0; } else if (Num[row - 1][col - 1] != 0) { Show(row - 1, col - 1, Num[row - 1][col - 1], v); } else { vector<vector<bool>> vis(n, vector<bool>(m, false)); BFS(row - 1, col - 1, v, Num, vis); ShowBroad(Num, vis); } //system("pause"); return 0; }