题目 1873: 蓝桥杯2017年第八届真题-合根植物

题目

w星球的一个种植园,被分成 m * n 个小格子(东西方向m行,南北方向n列)。每个格子里种了一株合根植物。
这种植物有个特点,它的根可能会沿着南北或东西方向伸展,从而与另一个格子的植物合成为一体。

题目 1873: 蓝桥杯2017年第八届真题-合根植物_第1张图片

输入
第一行,两个整数m,n,用空格分开,表示格子的行数、列数(1 接下来一行,一个整数k,表示下面还有k行数据(0 接下来k行,第行两个整数a,b,表示编号为a的小格子和编号为b的小格子合根了。

格子的编号一行一行,从上到下,从左到右编号。
比如:5 * 4 的小格子,编号:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
17 18 19 20

如果我们告诉你哪些小格子间出现了连根现象,你能说出这个园中一共有多少株合根植物吗?

输出
多少株

样例输入

5 4
16
2 3
1 5
5 9
4 8
7 8
9 10
10 11
11 12
10 14
12 16
14 18
17 18
15 19
19 20
9 13
13 17

样例输出

5

解题思路

本题是不需要回溯的深度优先搜索。不要回溯的原因是:只需要找到某一点作为起始点,所有能达到的“植物”即可,而不需要统计某一路径的长度等。

首先以vector存储邻接矩阵,len数组作为配套的数组,统计某一植物直接连接的所有植物总量(不用传统的二维数组是因为二维数组大小固定,浪费空间,且会出现空间过大的状况,可见“错误代码”部分),同时,建立hash散列,存放第i个的植物的位置是否被访问。

之后进行深度优先的搜索,起始通过遍历选择未经过访问的植物,每一次深度搜索都访问所有与该点直接或间接连接的植物,访问后合跟植物植物加一,并在DFS时将访问到的植物位置在hash当中标定为1,以免之后重复访问;如此循环,直到所有植物位置都被访问结束,输出合跟植物数目。

易错点

不要重复访问数目;且遇到稀疏的邻接矩阵,以vector存储可以节约空间。

代码

#include
using namespace std;
vector <int> dp[1000000]; 
int len[1000000];//记录dp每一个数字可以通向的树木
int m,n;//格子的行数、列数(1
int h[1000001];//记录该点是否被遍历了

void DFS(int now){
    int i,t;
    h[now] = 1;//表示已经走过
    for (i=0;i<len[now];i++)
    {
        t = dp[now][i];
        if (h[t]==0)
        {
            h[t] = 1;//标定该根已经遍历,避免重复
            DFS(t);
        }
    }
}

int main()
{
    long int num=0;
	int i,j,t1,t2,temp,k;//k行数据
	scanf("%d %d\n%d",&m,&n,&k);
	for (i=1;i<=k;i++)//读入,构建邻接矩阵
	{
	    scanf("%d %d",&t1,&t2);
	    dp[t1].push_back(t2);
	    dp[t2].push_back(t1);
	    len[t1]++;
	    len[t2]++;
	}
	for (i=1;i<=m;i++)
	{
	    for (j=1;j<=n;j++)
	    {
	        temp = (i-1)*n+j;
	        if (h[temp]==1)
	            continue;
	        else
	        {
	            DFS(temp);
	            num++;
	        }
	    }
	}
	printf("%ld",num);
	return 0;
}

错误代码

定义的长度固定的dp邻接矩阵的下标越界了(43分)

#include
int dp[1000][1000];//邻接矩阵
int m,n;//格子的行数、列数(1
int hash[1000001];//记录该点是否被遍历了
void DFS(int now){
    int i;
    hash[now] = 1;//表示已经走过
    for (i=1;i<=(m*n);i++)
    {
        if (hash[i]==0 && dp[now][i]==1)
        {
            dp[now][i] = 0;
            dp[i][now] = 0;//避免重复
            DFS(i);
        }
    }
}

int main()
{
    long int num=0;
	int i,j,t1,t2,temp,k;//k行数据
	scanf("%d %d\n%d",&m,&n,&k);
	for (i=1;i<=k;i++)//读入,构建邻接矩阵
	{
	    scanf("%d %d",&t1,&t2);
	    dp[t1][t2] = 1;
	    dp[t2][t1] = 1;
	}
	for (i=1;i<=m;i++)
	{
	    for (j=1;j<=n;j++)
	    {
	        temp = (i-1)*n+j;
	        if (hash[temp]==1)
	            continue;
	        else
	        {
	            DFS(temp);
	            num++;
	        }
	    }
	}
	printf("%ld",num);
	return 0;
}

你可能感兴趣的:(蓝桥杯真题(C/C++),蓝桥杯,c语言,深度优先)