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 的种子。
输入的第 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]; 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; }
|