经典贪心题NOP 1205流水线调度

对于加工顺序相同的两个或两个以上作业在两台机器上的加工排序,称之为:n个作业两台机床的作业排序问题,经典的启发式排序方法为Johnson规则。

思路:

先构成生产周期最短的最优作业顺序:

1.把作业分为两类,

A类 : 第一个花的作业的时间< 第二个花的作业的时间

B类 : 第一个花的作业的时间>= 第二个花的作业的时间

2.排序

对A类进行排序:按第一个花的作业的时间从小到大

对B类进行排序:按第二个花的作业的时间从大到小

3.合并

把A类B类作业合并即为生产周期最短的最优作业顺序

#include<stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
#define max_v 50005
struct node{
    int x,y,i;
}p[max_v],pp[max_v];
bool cmp1(node a,node b){
    return a.x<b.x;
}
bool cmp2(node a,node b){
    return a.y>b.y;
}
int main()
{
    int n;
    while(~scanf("%d",&n)){
        int len1=0,len2=0;
        int x,y;
        for(int i=0;i<n;i++){
            scanf("%d %d",&x,&y);
            if(x<y){
                p[len1].x=x;
                p[len1].i=i+1;//第几个作业
                p[len1++].y=y;
            }
            else{
                pp[len2].x=x;
                pp[len2].i=i+1;//第几个作业
                pp[len2++].y=y;
            }
        }
        sort(p,p+len1,cmp1);
        sort(pp,pp+len2,cmp2);
        for(int i=len1;i<len1+len2;i++){
            p[i]=pp[i-len1];
        }
        cout<<"输出他们作业的顺序:"<<endl;
        for(int i=0;i<len1+len2;i++)
            cout<<p[i].i<<" ";
        cout<<endl;
        int sum=p[0].x;
        int res=p[0].x+p[0].y;
        for(int i=1;i<n;i++)
        {
            sum+=p[i].x;
            res=max(res,sum)+p[i].y;
        }
        cout<<"输出他们最少所用的时间:"<<endl;
        printf("%d\n",res);
    }
    return 0;
}

 

#include<stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
#define max_v 50005
struct node{
    int x,y,i;
}p[max_v],pp[max_v];
bool cmp1(node a,node b){
    return a.x<b.x;
}
bool cmp2(node a,node b){
    return a.y>b.y;
}
int main()
{
    int n;
    while(~scanf("%d",&n)){
        int len1=0,len2=0;
        int x,y;
        for(int i=0;i<n;i++){
            scanf("%d %d",&x,&y);
            if(x<y){
                p[len1].x=x;
                p[len1].i=i+1;//第几个作业
                p[len1++].y=y;
            }
            else{
                pp[len2].x=x;
                pp[len2].i=i+1;//第几个作业
                pp[len2++].y=y;
            }
        }
        sort(p,p+len1,cmp1);
        sort(pp,pp+len2,cmp2);
        for(int i=len1;i<len1+len2;i++){
            p[i]=pp[i-len1];
        }
//        cout<<"输出他们作业的顺序:"<<endl;
//        for(int i=0;i<len1+len2;i++)
//            cout<<p[i].i<<" ";
//        cout<<endl;
        int sum=p[0].x;
        int res=p[0].x+p[0].y;
        for(int i=1;i<n;i++)
        {
            sum+=p[i].x;
            res=max(res,sum)+p[i].y;
        }
//        cout<<"输出他们最少所用的时间:"<<endl;
        printf("%d\n",res);
    }
    return 0;
}
NOIP 1205

 

动态规划的思想:

https://blog.csdn.net/huang1600301017/article/details/81022658

贪心算法训练:

 

https://www.cnblogs.com/NikkiNikita/p/9458496.html

https://blog.csdn.net/qq_39382769/article/month/2018/07/1?

 

思路:Johnson算法:
1:将任务分为两类,A类任务t1<t2,B类任务t1>=t2
2:两类任务分别排序,其中A类按 t1 递增排序,B类按 t2 递减排序
3:合并两类,将第二类任务接到第一类任务后面,此时任务的顺序最佳
4:遍历所有任务,计算总耗时
说下我的理解,对于 t1作业来说肯定是一直运行的,那么对于 t2 作业则会有 空闲和堆积两种境况,按照最小耗时,显然是不允许出现空闲情况的,因此 要先将 作业中 t1<t2的 按照 t1递增的顺序执行,这样便不会出现空闲情况,对于 剩余作业中就是 t1 >=t2的作业了,此时t2作业还处于堆积情况中,当每执行一个作业,由于 t1>=t2,t2作业中堆积的作业耗时会越来越小,因此要先将 t2较大的先执行,否则t2较大的滞留在最后便会增加耗时,因此再将 t1>=t2的作业按照 t2递减的顺序执行,如此便为最小耗时。

/*
Johnson算法:
1:将任务分为两类,A类任务t1<t2,B类任务t1>=t2
2:两类任务分别排序,其中A类按 t1 递增排序,B类按 t2 递减排序
3:合并两类,将第二类任务接到第一类任务后面,此时任务的顺序最佳
4:遍历所有任务,计算总耗时
*/
#include<iostream>
#include<algorithm> 
using namespace std;
typedef long long LL;
 
struct node {
    int time;
    int id;
    bool group;
    bool operator<(const node &p){
        return time<p.time;
    }
};
 
const int MAX_N=50005;
int n;
int a[MAX_N],b[MAX_N];
node d[MAX_N];
int best[MAX_N];
 
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>a[i]>>b[i];
    for(int i=0;i<n;i++){
        d[i].time=a[i]>b[i]?b[i]:a[i];
        d[i].id=i;
        d[i].group=a[i]<=b[i];
    }
    sort(d,d+n);
    int l=0,r=n-1;
    for(int i=0;i<n;i++)
        if(d[i].group) best[l++]=d[i].id;
        else    best[r--]=d[i].id;
    LL sum=0,ans=0;
    for(int i=0;i<n;i++)
    {
        sum+=a[best[i]];
        ans=max(ans,sum)+b[best[i]];
    }
    cout<<ans<<endl;
//    for(int i=0;i<n;i++)
//        printf("%d ",best[i]+1);
//    printf("\n");
    return 0;
} 

 

转载于:https://www.cnblogs.com/Aiahtwo/p/11351377.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值