快来踩爆这个蒟蒻吧|

Little_corn

园龄:1年1个月粉丝:11关注:17

2024-04-25 13:13阅读: 10评论: 0推荐: 0

P1248 加工生产调度

link

Solution:

贪心神仙题。

tips: 对于贪心题目,先考虑两个东西时的情况,一般是可以扩展到多个东西的情况的

此时我们考虑两订单 ij

  • ij : a[i]+max(b[i],a[j])+b[j]

  • ji : a[j]+max(b[j],a[i])+b[i]

此时我们按这个东西来做 cmp 就会发现它不对。

为什么呢?

因为这个东西它不具有传递性

如果仔细想想,就会发现按这个排序,对于排完序后下标递增的三个数 i,j,k,他可能不是最优解。说白了,就是这个东西是局部最优解,它不能拓展为全局最优解

(然鹅这个时候我就不会了)

那么我们感性理解一下,越少时间的工序对后面的影响越小。于是我们在两个数组未被安排过的里面找最小值。

找到的最小值可能在 a 也有可能在 b ,分讨一下:

1.若最小值是 ai ,则此时对于任何一个未被安排的工序 j ,一定有 aiaj,bi,bj 。对于上式化简,显然的,应该将 i 工序安排在 j 工序前。

2.若最小值是 bi ,同理可得,对于任何一个未被安排过得工序 j 要将 j 工序安排在 i 工序前。

那么做法也就一目了然了:

  • 先找到 ab 中没有安排过工序中的时间最小值。

  • 若最小值在 a 数组中,则将此工序安排在未安排工序的首部。

  • 若最小值在 b 数组中,则将此工序安排在未安排工序的尾部。

  • 求完顺序后模拟一次得到答案

code:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e4+10;
int order[N],lo,ro;// order 是安排顺序,lo、ro是左端点和右端点
int n,a[N],b[N];
struct node{
int c,id;// id 为原数组中的编号,c=min(a[i],b[i])
bool lft;// 是放在首部还是尾部
}rk[N];
bool cmp(struct node n1,struct node n2){
return n1.c<n2.c;
}
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>b[i];
for(int i=1;i<=n;i++){
rk[i].id=i;rk[i].c=min(a[i],b[i]);
if(rk[i].c==a[i])rk[i].lft=true;// a[i] 小则放在首部
else rk[i].lft=false;// 否则就是尾部
}
sort(rk+1,rk+n+1,cmp);
lo=1,ro=n;
for(int i=1;i<=n;i++){
if(rk[i].lft)order[lo++]=rk[i].id;
else order[ro--]=rk[i].id;
}
int ta=0,tb=0;// A 厂和 B 厂的最后一工序结束时间
for(int i=1;i<=n;i++){
int x=order[i];
ta+=a[x];tb=max(ta,tb)+b[x];// 直接模拟
}
cout<<max(ta,tb)<<endl;
for(int i=1;i<=n;i++)cout<<order[i]<<" ";
return 0;
}

本文作者:Little_corn

本文链接:https://www.cnblogs.com/little-corn/p/18157456

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Little_corn  阅读(10)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起