【u006】海战
Time Limit: 1 second
Memory Limit: 128 MB
【问题描述】
在峰会期间,武装部队得处于高度戒备。警察将监视每一条大街,军队将保卫建筑物,领空将布满了F-2003飞机。此外,巡洋船只和舰队将被派去保护海岸线。不幸的是因为种种原因,国防海军部仅有很少的几位军官能指挥大型海战。因此,他们考虑培养一些新的海军指挥官,他们选择了“海战”游戏来帮助学习。 在这个著名的游戏中,在一个方形的盘上放置了固定数量和形状的船只,每只船却不能碰到其它的船。在这个题中,我们仅考虑船是方形的,所有的船只都是由图形组成的方形。编写程序求出该棋盘上放置的船只的总数。
【输入格式】
头一行由用空格隔开的两个整数R和C组成,1<=R,C<=1000,这两个数分别表示游戏棋盘的行数和列数。接下来的R行每行包含C个字符,每个字符可以为“#”,也可为“.”,“#”表示船只的一部分,“.”表示水。
【输出格式】
为每一个段落输出一行解。如果船的位置放得正确(即棋盘上只存在相互之间不能接触的方形,如果两个“#”号上下相邻或左右相邻却分属两艘不同的船只,则称这两艘船相互接触了)。就输出一段话“There are S ships.”,S表示船只的数量。否则输出“Bad placement.”。
Sample Input
6 8 .....#.# ##.....# ##.....# .......# #......# #..#...#
Sample Output
There are 5 ships.
【题解】
像是这样
我们称其为出错的类型。
可以这样。
在进行连通块的广搜的时候。
记录其出现过的坐标最左上和最右下是什么。
比如新加入一个坐标(x,y)到队列中
判断是否x小于x1,如果是则更新x1,判断是否y小于y1,是则更新y1;
判断是否x大于x2,如果是则更新x2,判断是否y大于y2,是则更新y2;
这样我们就可以得到这一片区域的左上角和右下角所在的坐标
比如
我们得到的x1,y1是(1,2);得到的x2,y2是(3,3);
然后发现(1,2)->(3,3)这个矩形框架内有'.',则输出错误信息。
然后如果没有出错就输出连通块的个数即可。
【代码】
#include <cstdio> #include <stdlib.h> const int dx[5] = { 0,1,-1,0,0 }; const int dy[5] = { 0,0,0,1,-1 }; int r, c,dl[1000001][2],final_ans = 0; bool bo[1001][1001] = { 0 }, visited[1001][1001] = { 0 }; void input_data(); void get_ans(); void bfs(int, int); void output_ans(); int main() { input_data(); get_ans(); output_ans(); return 0; } void output_ans() { printf("There are %d ships.", final_ans);//输出有几条船 } void bfs(int x, int y)//从x,y开始寻找连通块 { int h = 0, t = 1; dl[1][0] = x; dl[1][1] = y;//把(x,y)加入到队列中去。 visited[x][y] = true; int x1, y1, x2, y2; x1 = x, y1 = y, x2 = x, y2 = y;//一开始左上角、右下角的坐标是一样的。 while (h != t)//进行广搜。 { h++; for (int i = 1; i <= 4; i++)//往4个方向扩展。 { int xx = dl[h][0]+dx[i], yy = dl[h][1]+dy[i]; if (bo[xx][yy] && !visited[xx][yy])//如果是船的一部分且没有访问过 { if (xx < x1) x1 = xx; if (yy < y1) y1 = yy; if (xx > x2) x2 = xx; if (yy > y2) y2 = yy;//更新左上角和右下角的坐标。 visited[xx][yy] = true;//标记这个点已经访问过了。 t++;//队列的尾节点递增 dl[t][0] = xx;//把新的点加入到队列中去。 dl[t][1] = yy; } } } for (int i = x1;i <= x2;i++) for (int j = y1;j <= y2;j++)//如果在左上角和右下角的这个矩形框架内有'.'(水) if (!bo[i][j]) //则说明出错了。直接输出错误信息,然后结束所有的程序。 { printf("Bad placement."); exit(0); } } void get_ans() { for (int i = 1; i <= r; i++) for (int j = 1; j <= c; j++)//如果是船的一部分,且没有访问过。则进入进行广搜 if (bo[i][j] && !visited[i][j]) bfs(i, j),final_ans++;//同时递增答案 } void input_data() { scanf("%d%d", &r, &c);//输入行数和列数 char s[1500]; for (int i = 1; i <= r; i++)//输入r行的字符串 { scanf("%s", s); for (int j = 1; j <= c; j++)//字符串的大小就是c. if (s[j - 1] == '.') bo[i][j] = false; else bo[i][j] = true; } }