面试题:P1-数海岸线算法

这是一个比较偏僻的网站上的题目,做这个题目的原因是某同学去面试的时候遇到了这样的题目,然后问我如何做,遇上这样的问题不解决就不是我的风格了。

先给出这个网站的题目网址:http://jobs.p1.com/tech/costal.html

估计很少人上个这个网站,做个这个网站的题目更加少了,所以有公司拿这样的现成的题目考面试者,有面试者做过了的概率是很少的。不过只要学校不太糟糕,那么能做出这样题目的人,进个什么BAT不是什么难事吧。


同时贴出题目吧:

Coast Length

Puzzle ID: coast



The island municipality of Soteholm is required to write a plan of action for their work with emission of greenhouse gases. They realize that a natural first step is to decide whether they are for or against global warming. For this purpose they have read the IPCC report on climate change and found out that the largest effect on their municipality could be the rising sea level.

The residents of Soteholm value their coast highly and therefore want to maximize its total length. For them to be able to make an informed decision on their position in the issue of global warming, you have to help them find out whether their coastal line will shrink or expand if the sea level rises. From height maps they have figured out what parts of their islands will be covered by water, under the different scenarios described in the IPCC report, but they need your help to calculate the length of the coastal lines.



Task

You will be given a map of Soteholm as an N×M grid. Each square in the grid has a side length of 1 km and is either water or land. Your goal is to compute the total length of sea coast of all islands. Sea coast is all borders between land and sea, and sea is any water connected to an edge of the map only through water. Two squares are connected if they share an edge. You may assume that the map is surrounded by sea. Lakes and islands in lakes are not contributing to the sea coast.



Figure 1: 
Gray squares are land and white squares are water. The thick black line is the sea coast. This example corresponds to Sample Input 1.




Input

The first line of the input contains two space separated integers N and M where 1 ≤ N, M ≤ 1000. The following N lines each contain a string of length M consisting of only zeros and ones. Zero means water and one means land.


Output

Output one line with one integer, the total length of the coast in km.


Sample Input 1

 

Sample Output 1


5 6 
011110
010110 
111000
000010 
000000

 

 

20



To submit a solution to this problem, send an e-mail to challenge@p1.cn

Include your source code files as attachments and set the subjectline to coast. 
You should receive an answer within minutes. (make sure the subjectline is exactly: coast)


出处:http://jobs.p1.com/tech/costal.html


看上面的图就大概能明白,就是上图四周是大海包围的,数海岸线的长度,其中中间空的算是湖岸线了,不能算是海岸线,这就是其中的难点。


主要算法要点:

1 以地图的四周,即地图的边沿,如下图黄色部分:


作为收拾搜索点,使用递归搜索,如果是0,代表是海水能渗入的地方,那么就做好标识,我的代码使用const char WATER = '2',标识;沿这样的点能走到的点都标识为WATER,这样就能标识出海水渗透到的格子,并和内湖的格子区分开来了。



2 第1步解决了标识和区分内湖的问题,然后就解决数海岸线的问题了,我们分开两步来数,第一步数最外边的海岸线,第二部数格子之间的海岸线;

即第一步数:



这里应该数作5条海岸线。

第二步数格子之间的海岸线:



这里应该数作30条海岸线,但是由于格子之间的海岸线会数重复,那么实际的海岸线应该是30/2=15条

最终5 + 15 = 20条海岸线。


理解了两个关键算法点之后,再写算法就不难了,只要处理好代码细节问题就好了。

由于这个网站的判断系统对我来说也比较新,故此对一个新系统的输入输出处理和判别系统都需要熟悉以下,故此多调试以下是必然的了。


最后给出AC的代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <vector>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <string>
#include <limits.h>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;

const int MAX_N = 1001;
char arr[MAX_N][MAX_N];
int n, m;
const char WATER = '2';

inline bool isLegal(int r, int c)
{
	return 0<=r && 0<=c && r<n && c<m;
}

void fillWater(int r, int c)
{
	if (!isLegal(r, c)) return ;
	if (arr[r][c] != '0') return ;

	arr[r][c] = WATER;
	fillWater(r-1, c);
	fillWater(r+1, c);
	fillWater(r, c-1);
	fillWater(r, c+1);
}

int main()
{
	//freopen("in.txt", "r", stdin);
	scanf("%d %d", &n, &m);
	getchar();
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			char a = getchar();
			while (a != '0' && a != '1')
			{
				a = getchar();
			}///< handle io crazy problems.
			arr[i][j] = a;
		}
	}
	for (int i = 0; i < n; i++)
	{
		fillWater(i, 0);
		fillWater(i, m-1);
	}
	for (int j = 1; j+1 < m; j++)
	{
		fillWater(0, j);
		fillWater(n-1, j);
	}

	int outEdge = 0, inEdge2 = 0;

	for (int i = 0; i < n; i++)
	{
		if (arr[i][0] != WATER) outEdge++;
		if (arr[i][m-1] != WATER) outEdge++;
	}
	for (int j = 0; j < m; j++)
	{
		if (arr[0][j] != WATER) outEdge++;
		if (arr[n-1][j] != WATER) outEdge++;
	}

	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			if (arr[i][j] == WATER)
			{
				if (isLegal(i-1, j))
				{
					if (arr[i-1][j] != WATER) inEdge2++;
				}
				if (isLegal(i+1, j))
				{
					if (arr[i+1][j] != WATER) inEdge2++;
				}
				if (isLegal(i, j-1))
				{
					if (arr[i][j-1] != WATER) inEdge2++;
				}
				if (isLegal(i, j+1))
				{
					if (arr[i][j+1] != WATER) inEdge2++;
				}
			}
			else if (arr[i][j] != WATER)
			{
				if (isLegal(i-1, j))
				{
					if (arr[i-1][j] == WATER) inEdge2++;
				}
				if (isLegal(i+1, j))
				{
					if (arr[i+1][j] == WATER) inEdge2++;
				}
				if (isLegal(i, j-1))
				{
					if (arr[i][j-1] == WATER) inEdge2++;
				}
				if (isLegal(i, j+1))
				{
					if (arr[i][j+1] == WATER) inEdge2++;
				}
			}
		}
	}
	printf("%d", outEdge + (inEdge2>>1));
	return 0;
}




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值