【蓝桥杯2020省赛】【深度优先搜索】作物杂交(详解!)

目录

题目

题目链接

输入描述

输出描述

测试样例

输入样例

输出样例

提交结果截图

详细分析

带详细注释的源代码


题目

作物杂交是作物栽培中重要的一步。已知有 N种作物 (编号 1 至 N ),第 i 种作物从播种到成熟的时间为 Ti​。作物之间两两可以进行杂交,杂交时间取两种中时间较长的一方。如作物 A 种植时间为 5 天,作物 B 种植时间为 7 天,则 AB 杂交花费的时间为 7 天。作物杂交会产生固定的作物,新产生的作物仍然属于 N 种作物中的一种。

初始时,拥有其中 M 种作物的种子 (数量无限,可以支持多次杂交)。同时可以进行多个杂交过程。求问对于给定的目标种子,最少需要多少天能够得到。

如存在 4 种作物 ABCD,各自的成熟时间为 5 天、7 天、3 天、8 天。初始拥有 AB 两种作物的种子,目标种子为 D,已知杂交情况为 A × B → C,A × C → D。则最短的杂交过程为:

第 1 天到第 7 天 (作物 B 的时间),A × B → C。

第 8 天到第 12 天 (作物 A 的时间),A × C → D。

花费 12 天得到作物 D 的种子。

题目链接

作物杂交 - 蓝桥云课 (lanqiao.cn)icon-default.png?t=L9C2https://www.lanqiao.cn/problems/506/learning/

输入描述

输入的第 1 行包含 4 个整数 N, M, K, TN,M,K,T,NN 表示作物种类总数 (编号 11 至 NN),MM 表示初始拥有的作物种子类型数量,KK 表示可以杂交的方案数,TT 表示目标种子的编号。

第 2 行包含 NN 个整数,其中第 ii 个整数表示第 ii 种作物的种植时间 T_i\ (1 \leq T_i \leq 100)Ti​ (1≤Ti​≤100)。

第 3 行包含 MM 个整数,分别表示已拥有的种子类型 K_j\ (1 \leq K_j \leq M)Kj​ (1≤Kj​≤M),K_jKj​ 两两不同。

第 4 至 KK + 3 行,每行包含 3 个整数 A, B,CA,B,C,表示第 AA 类作物和第 BB 类作物杂交可以获得第 CC 类作物的种子。

其中,1≤N≤2000, 2≤M≤ N, 1≤K≤10^5, 1≤T≤N 1≤N≤2000,2≤M≤N,1≤K≤105,1≤T≤N, 保证目标种子一定可以通过杂交得到。

输出描述

输出一个整数,表示得到目标种子的最短杂交时间。

测试样例

输入样例

6 2 4 6
5 3 4 6 4 9
1 2
1 2 3
1 3 4
2 3 5
4 5 6

输出样例

16

提交结果截图

【蓝桥杯2020省赛】【深度优先搜索】作物杂交(详解!)_第1张图片 

详细分析

1.【数据结构】

我们改如何存储每种作物的所有杂交方案呢?

我开始想到是用二维数组存储,定义一个足够大的数组int hybrid[2005][2005],存储所有杂交方案,如A + B->C,转换为hybrid[A][B] = C.

但是使用这种存储方案的的话,我想不到该如何去得到一种种子的最短杂交时间,因为目标种子是数组所存的值,我们需要的是通过目标种子的标号能够得到能够杂交出该种子的所有杂交方案!

所以这种方案肯定是不行的。

我又想出来一种通过二维向量(vector)来存储的办法。

定义一个二维向量vector< vector >hybrid(2005);存储每种作物的所有杂交方案

定义一个结构体存储杂交方案

struct parent //存储杂交方案
{    
    int x;
    int y;
}; 

每次输入一个能杂交出 x 作物的杂交方案(parent类型存储)就存入hybrid[x] 中。

 2.【递归求解】

 递归部分在代码中写得很详细了,就不细写了,有不懂的欢迎评论留言!

带详细注释的源代码

#include 
#include 
#include "string.h"
#include 
using namespace std;

struct parent //存储杂交方案
{	
	int x;
	int y;
};
int n, m, k, t, tmp;
long long plant_time[2005];//每种作物的种植时间
bool flag[2005];//标记是否出现了该作物
long long min_hybrid_time[2005];//杂交出每种作物的最短时间
vector< vector >hybrid(2005);//存储每种作物的所有杂交方案

long long solve(int now)
{
	if (flag[now])//若是已有杂交出该种作物的最短时间
		return min_hybrid_time[now];//直接返回即可

	for (int i = 0; i < hybrid[now].size(); i++)//对能够杂交出当前作物的方案都尝试一下
	{
		parent tmp = hybrid[now][i];//能够杂交出当前作物的第i种方案
		//当前作物的最短杂交时间是 杂交出该作物的所有方案 中的最短时间
		//而每种方案的最短时间是种植其‘父母’作物所需要的时间 + 其父母作物杂交所需的的最短时间(=两者杂交所需时间中的最大值)
		min_hybrid_time[now] = min(min_hybrid_time[now], max(plant_time[tmp.x], plant_time[tmp.y]) + max(solve(tmp.x), solve(tmp.y)));
	}
	flag[now] = true;//标记已经找到最短杂交时间
	return min_hybrid_time[now];//返回最短杂交时间
}

int main()
{
	cin >> n >> m >> k >> t;
	memset(min_hybrid_time, 0x3f, sizeof(min_hybrid_time));//杂交出每种作物的最短时间初始化为最大值
	memset(flag, false, sizeof(flag));//作物标记初始化
	//注意作物的下标从1开始!!!
	for (int i = 1; i <= n; i++)//输入种植时间
		cin >> plant_time[i];
	for (int i = 0; i < m; i++)//输入初始种子数据
	{
		cin >> tmp;
		flag[tmp] = true;//标记已经有了最短杂交时间
		min_hybrid_time[tmp] = 0;//最短杂交时间 = 0,因为不需要杂交
	}
	for (int i = 0; i < k; i++)//输入所有杂交方案
	{
		parent temp;
		cin >> temp.x >> temp.y >> tmp;
		hybrid[tmp].push_back(temp);//存储杂交方案
	}
	solve(t);//递归求解
	cout << min_hybrid_time[t] << endl;//输出杂交出目标作物的最短时间
	return 0;
}

你可能感兴趣的:(蓝桥杯,蓝桥杯,省赛,2020,搜索,详解)