coding笔记: acwing 3305 作物杂交
sixwalter Lv6

Acwing 3305 作物杂交

Content

作物杂交是作物栽培中重要的一步。

已知有 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 的种子。

Input

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

第 2 行包含 N 个整数,其中第 i 个整数表示第 i 种作物的种植时间 Ti。

第 3 行包含 M 个整数,分别表示已拥有的种子类型 Kj,Kj 两两不同。

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

1
2
3
4
5
6
1≤N≤2000,
2≤M≤N,
1≤K≤105,
1≤T≤N,
1≤Ti≤100,
1≤Kj≤M,

Output

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

Code

initial version of the solution (the following picture is great, there’s no need drawing again)

  • the first version actually has two dimensions as illustrated by the picture above
  • it is essentially a DP solution!
  • how to store edges is the key

second version, I optimize the first dimension

Complexity: , where N is the seed number, and M is the Process number

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include<iostream>
#include<cstring>
#include<vector>

using namespace std;

struct Process{
int a,b,c;
};
const int N = 2010;
int mature_time[N];
int f[N];
vector<Process> ps;


void bellmanfold(int n){
for(int i=1;i<n;++i){
for(auto pro: ps){
if(max(f[pro.a],f[pro.b])+max(mature_time[pro.a],mature_time[pro.b])<f[pro.c]){
f[pro.c] = max(f[pro.a],f[pro.b])+max(mature_time[pro.a],mature_time[pro.b]);
}
}
}
}
int main(){
int n,m,k,t;
scanf("%d%d%d%d",&n,&m,&k,&t);
for(int i=1;i<=n;++i){
scanf("%d",&mature_time[i]);
}
memset(f,0x3f,sizeof f);
for(int i=0;i<m;++i){
int x;
scanf("%d",&x);
f[x]=0;
}
for(int i=0;i<k;++i){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
ps.push_back({a,b,c});
}
bellmanfold(n);
printf("%d\n",f[t]);

return 0;
}

Third version, use QUEUE to optimize the solution!

Complexity: normally , worstly

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;

struct Process{
int a,b,c;
Process *ne=nullptr;
Process(int a, int b, int c, Process* ne):a(a),b(b),c(c),ne(ne){}
};

const int N = 2010;
int mature_time[N];
int f[N];
Process* ps[N]; // build a neighbor table
queue<int> que;
bool inQue[N];

void insert(int a, int b, int c){
Process * np = new Process(a,b,c,ps[a]);
ps[a] = np;
np = new Process(b,a,c,ps[b]);
ps[b] = np;
}

void spfa(){
while(!que.empty()){
int cu = que.front();
que.pop();
inQue[cu] = false;
for(auto i = ps[cu]; i!=nullptr; i = i->ne){
if(max(f[i->a],f[i->b])+max(mature_time[i->a],mature_time[i->b])<f[i->c]){
f[i->c] = max(f[i->a],f[i->b])+max(mature_time[i->a],mature_time[i->b]);
if(!inQue[i->c]){
que.push(i->c);
inQue[i->c] = true;
}
}
}
}
}
int main(){
int n,m,k,t;
scanf("%d%d%d%d",&n,&m,&k,&t);
for(int i=1;i<=n;++i){
scanf("%d",&mature_time[i]);
}
memset(f,0x3f,sizeof f);
for(int i=0;i<m;++i){
int x;
scanf("%d",&x);
f[x]=0;
que.push(x);
}
for(int i=0;i<k;++i){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
insert(a,b,c);
}
spfa();
printf("%d\n",f[t]);

return 0;
}
  • Post title:coding笔记: acwing 3305 作物杂交
  • Post author:sixwalter
  • Create time:2023-08-05 11:14:26
  • Post link:https://coelien.github.io/2023/08/05/coding-solution/acwing_3305/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.
 Comments