最优转载问题
部分背包问题
乘船问题
选择不相交区间问题
区间选点问题
流水作业问题
1425:【例题4】加工生产调度
时间限制: 1000 ms 内存限制: 65536 KB提交数: 564 通过数: 130
【题目描述】
某工厂收到了 nn 个产品的订单,这 nn 个产品分别在 A、B 两个车间加工,并且必须先在 A 车间加工后才可以到 B 车间加工。
某个产品 ii 在 A,B 两车间加工的时间分别为Ai,BiAi,Bi。怎样安排这 nn 个产品的加工顺序,才能使总的加工时间最短。
这里所说的加工时间是指:从开始加工第一个产品到最后所有的产品都已在 A,B 两车间加工完毕的时间。
【输入】
第一行仅—个数据 nn ,表示产品的数量;
接下来 nn 个数据是表示这 nn 个产品在 A 车间加工各自所要的时间;
最后的 nn 个数据是表示这 nn 个产品在 B 车间加工各自所要的时间。
【输出】
第一行一个数据,表示最少的加工时间;
第二行是一种最小加工时间的加工顺序。
【输入样例】
5 3 5 8 7 10 6 2 1 4 9
【输出样例】
34 1 5 4 2 3
【提示】
对于100%的数据, 0 < n < 10000,所有数值皆为整数。
【题解】
贪心;
因为B机器在工作的时候,A机器还能够工作;
所以就这样;
对于A机器;
先找一个在A机器上加工时间短的产品;
让它在机器上加工完
尽早让B机器开始工作;
这样B机器和A机器它们的空闲时间就会最短了;
同时让B机器优先加工的产品时间尽量长一点;
这样同时在A机器上加工的产品就会尽可能地多;
总之就是让A机器和B机器的空闲时间尽可能地短;
/*
先找一个在A机器上加工时间短的产品;
同时让B机器优先加工的产品时间尽量长一点;
*/
上面这两句话就是关键了;
按照这个原则;
处理出m[i]=min(a[i],b[i]);
然后把m数组升序排;
然后顺序处理n个m[i];
如果m是由a数组搞来的,就放在数据的最前(如果前面有元素了就尽可能靠前,否则放在序列的最后(如果最后也有元素了就尽量靠后);
如样例,N=5
(A1,A2,A3,A4,A5)=(3,5,8,7,10)
(B1,B2,B3,B4,B5)=(6,2,1,4,9)
则(m1,m2,m3,m4,m5)=(3,2,1,4,9)
排序之后为(m3,m2,m1,m4,m5)
处理m3:因为m3=B3,所以m3排在后面;加入m3之后的加工顺序为( , , , ,3);
处理m2:因为m2=B2,所以m2排在后面;加入m2之后的加工顺序为( , , ,2,3);
处理m1:因为m2=A1,所以m1排在前面;加入m1之后的加工顺序为(1, , ,2,3);
处理m4:因为m4=B4,所以m4排在后面;加入m4之后的加工顺序为(1, ,4,2,3);
处理m5:因为m5=B5,所以m5排在后面;加入m5之后的加工顺序为(1,5,4,2,3);
则最优加工顺序就是(1,5,4,2,3),最短时间34。显然这是最优解。
然后根据序列模拟出总的时间就好;
(B机器在工作的时候,A机器也可以继续加工其他产品哦);
//2018-08-03 20:09:13 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 10001; int ans[N], a[N], b[N], m[N], s[N]; int n; int main(){ scanf("%d", &n); for(int i=1; i<=n; i++) scanf("%d", &a[i]); for(int i=1; i<=n; i++) scanf("%d", &b[i]); //********** for(int i=1; i<=n; i++){ m[i] = min(a[i], b[i]); s[i] = i; } for(int i=1;i<=n-1; i++) for(int j=i+1; j<=n; j++) if(m[i] > m[j]){ swap(m[i], m[j]); swap(s[i], s[j]); } int k=0, t=n+1; for(int i=1; i<=n; i++) if(m[i] == a[s[i]]){ k++; ans[k] = s[i]; }else{ t--; ans[t] = s[i]; } k = 0, t = 0; for(int i=1; i<=n; i++){ k += a[ans[i]]; if(t < k) t = k; t += b[ans[i]]; } printf("%d ", t); for(int i=1; i<=n; i++) printf("%d ", ans[i]); printf(" "); return 0; }
带期限和罚款的单位时间任务调度
1426:【例题5】智力大冲浪时间限制: 1000 ms
内存限制: 65536 KB提交数: 269 通过数: 199
【题目描述】
小伟报名参加中央电视台的智力大冲浪节目。本次挑战赛吸引了众多参赛者,主持人为了表彰大家的勇气,先奖励每个参赛者m元。
先不要太高兴!因为这些钱还不一定都是你的。接下来主持人宣布了比赛规则: 首先,比赛时间分为n个时段(n≤500),
它又给出了很多小游戏,每个小游戏都必须在规定期限ti前完成(1≤ti≤n)。如果一个游戏没能在规定期限前完成,
则要从奖励费m元中扣去一部分钱wi,wi为自然数,不同的游戏扣去的钱是不一样的。当然,每个游戏本身都很简单,
保证每个参赛者都能在一个时段内完成,而且都必须从整时段开始。主持人只是想考考每个参赛者如何安排组织自己做游戏的顺序。
作为参赛者,小伟很想赢得冠军,当然更想赢取最多的钱! 注意:比赛绝对不会让参赛者赔钱!
【输入】
输入共4行。
第一行为m,表示一开始奖励给每位参赛者的钱;
第二行为n,表示有n个小游戏; 第三行有n个数,分别表示游戏1~n的规定完成期限;
第四行有n个数,分别表示游戏1~n不能在规定期限前完成的扣款数。
【输出】
仅1行。表示小伟能赢取最多的钱。
【输入样例】
10000 7 4 2 4 3 1 4 6 70 60 50 40 30 20 10
【输出样例】
9950
【提示】
数据范围及提示:
n≤500,1≤ti≤n
思路:
按罚款由大到小排序;
然后从头开始吧任务安排在不超过期限且最接近期限的位置
#include<iostream> #include<algorithm> using namespace std; struct pp{ int w,t; }; pp p[505]; int vis[1000]; bool cmp(pp p1,pp p2){ if(p1.w!=p2.w) return p1.w>p2.w; else return p1.t>p2.t; } int main(){ int sum,n,tt,ww; cin>>sum>>n; for(int i=1;i<=n;i++) cin>>p[i].t; for(int i=1;i<=n;i++) cin>>p[i].w; sort(p+1,p+n+1,cmp); for(int i=1;i<=n;i++){ int j=p[i].t; while(vis[j]!=0){ j--; if(j==0) break; } if(j==0){ sum-=p[i].w; continue; } vis[j]=1; } cout<<sum<<endl; return 0; }