https://www.luogu.com.cn/problem/P1248
考虑2个产品,分别是
Ai Bi,Aj Bj
如果顺序是先i后j
若Bi>Aj,则用时为Ai+Bi+Bj
若Bi<Aj,则用时为Ai+Aj+Bj
所以先i后j用时为 Ai+max(Bi,Aj)+Bj
同理先j后i用时为 Aj+max(Bj,Ai)+Bi
令tot=Ai+Bi+Aj+Bj,式子变形:
Ai+max(Bi,Aj)+Bj = tot-min(Bi,Aj)
Aj+max(Bj,Ai)+Bi = tot-min(Bj,Ai)
所以
若min(Bi,Aj)>min(Bj,Ai),则先i后j
若min(Bi,Aj)<min(Bj,Ai),则先j后i
故得出解法:
将所有的A,B从小到大排序,产品队列设一个头指针,一个尾指针
取出当前最小的时间,若该时间对应产品还未入队
若该时间属于机器A的时间,则把给产品放到头指针出,头指针后移
因为
假设产品是i,min(Bi,Aj)>min(Bj,Ai) 在剩余产品中全部成立
假设产品时j,min(Bi,Aj)<min(Bj,Ai) 在剩余产品中全部成立
同理
若该时间属于机器B的时间,则把给产品放到尾指针出,尾指针前移
#include<cstdio> #include<algorithm> using namespace std; #define N 1001 struct node { int t,id; bool a; }e[N<<1]; int order[N]; bool use[N]; int ta[N],tb[N]; bool cmp(node p,node q) { return p.t<q.t; } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d",&ta[i]); e[i].id=i; e[i].a=true; e[i].t=ta[i]; } int m=n; for(int i=1;i<=n;++i) { scanf("%d",&tb[i]); e[++m].id=i; e[m].t=tb[i]; } sort(e+1,e+m+1,cmp); int l=0,r=n+1; for(int i=1;i<=m;++i) { if(use[e[i].id]) continue; use[e[i].id]=true; if(e[i].a) order[++l]=e[i].id; else order[--r]=e[i].id; } int nb=1,t; for(int i=2;i<=n;++i) { t=ta[order[i]]; if(tb[order[nb]]>t) tb[order[nb]]-=t; else while(t && nb<i) { if(tb[order[nb]]<=t) { t-=tb[order[nb]]; tb[order[nb]]=0; nb++; } else { tb[order[nb]]-=t; t=0; } } } long long ans=0; for(int i=nb;i<=n;++i) ans+=tb[order[i]]; for(int i=1;i<=n;++i) ans+=ta[i]; printf("%lld ",ans); for(int i=1;i<=n;++i) printf("%d ",order[i]); }
题目描述
某工厂收到了 nnn 个产品的订单,这 nnn 个产品分别在 A、B 两个车间加工,并且必须先在 A 车间加工后才可以到 B 车间加工。
某个产品 iii 在 A、B 两车间加工的时间分别为 Ai,BiA_i,B_iAi,Bi。怎样安排这 nnn 个产品的加工顺序,才能使总的加工时间最短。
这里所说的加工时间是指:从开始加工第一个产品到最后所有的产品都已在 A、B 两车间加工完毕的时间。
输入格式
第一行仅—个整数 nnn,表示产品的数量。
接下来一行 nnn 个整数是表示这 nnn 个产品在 A 车间加工各自所要的时间。
最后的 nnn 个整数是表示这 nnn 个产品在 B 车间加工各自所要的时间。
输出格式
第一行一个整数,表示最少的加工时间。
第二行是一种最小加工时间的加工顺序。
输入输出样例
5 3 5 8 7 10 6 2 1 4 9
34 1 5 4 2 3
说明/提示
1≤n≤10001leq nleq 10001≤n≤1000。