加工生产调度

在这里插入图片描述
在这里插入图片描述

心路历程(如果你没有时间请直接跳到下一板块(。・_・)/~~~)

针对于这道题,一开始博主并不知道也没有用所谓的Johnson算法;
① 当博主发现这是一道贪心算法的时候,也没有很直接的思路和策略,所以博主就用了最直接的a车间的工作时间除以b车间的工作时间水过了44分的数据
在这里插入图片描述

bool mycmp(number x,number y)
{
    return x.c<y.c;
}
 for(int i=1;i<=n;i++)
    {
        num[i].b=read();
        num[i].c=(num[i].a*1.0)/(num[i].b*1.0);//这个就是博主的鬼畜求商
    }
    sort(num+1,num+n+1,mycmp);
    //这些是部分代码

//下面是模拟求和

 ans+=num[1].a;
    for(int i=1;i<n;i++)
    {
        ans+=num[i].b;
        int tot=num[i+1].a-num[i].b;
        ans+=tot;
    }
    ans+=num[n].b;
    printf("%lld\n",ans);

② 当博主发现并不能解决这道题的时候,又思考了好长时间(或许是博主太弱了),博主发现实际上a车间的工作是连续不停的!!于是乎,博主就
想到了用a车间的总时间加上b车间的最小值,因为在a车间完成之后,b车间应该是会有剩余一件的物品,此时若使b车间最后加工的一件物品的工作时间最小,那么不就是总时间最小了吗!!!!!!呵呵,天真=_=)(然后就水过了76分
在这里插入图片描述

for(int i=1;i<=n;i++)
    {
        num[i].id=i;
        num[i].a=read();
        sum1+=num[i].a;//sum1和sum2在这里分别是a车间的工作总和和b车间的工作总和
        a1=min(a1,num[i].a);//a1,b1分别是a车间的最小的工作时间和b车间的最小工作时间
    }
    for(int i=1;i<=n;i++)
    {
        num[i].b=read();
        num[i].c=(num[i].a*1.0)/(num[i].b*1.0);//依旧是上面的鬼畜算法
        b1=min(b1,num[i].b);
        sum2+=num[i].b;
    }
    sort(num+1,num+1+n,mycmp);
    if(sum1>sum2)
    {
        ans+=sum1;
        ans+=b1;
    }
    else
    {
        ans+=sum2;
        ans+=a1;
    }
    printf("%lld\n",ans);

现在博主想到自己之前的种种做法发现这其中都是有问题
1.首先先说贪心策略(就是内个鬼畜算法的排列方式)是博主灵光一现 瞎诌出来的,缺乏证明(但是不得不说是可以水 分的 );
2.模拟的时候就是根本没有一个依据啥的就是在瞎搞;

这是正文!

针对于A,B车间,A车间是一直在运作,而B车间中间是有空缺的,因为有时候,B车间会因为等待A车间的第一次生产而需要更多的时间
那么这个时候,就可以想一下,应该如何排序的呢?使得B车间中的空闲时间最少。

可以自己稍微思考一下,如果不会就看一下下面的正确策略。

①策略:让在A车间中花费时间最少的在前面(这样子的话,就会让B最先开始开工,那么一开始等待的时间就会较少一些),让在B车间中工作时间最少的放在最后(那么就是在A车间工作结束后,B车间工作的时间最少),这样的话就会很好的处理到了A,B车间的空闲时间最少,从而得到了最少的工作时间。
部分处理代码如下

	struct number
	{
	    int id,a,b,m;
	};
	number num1[1010];//这里面保存的是原始的排列顺序
	number num2[1010];//这里面保存的是排列后的顺序
	
 for(int i=1;i<=n;i++)
    {
        num1[i].b=read();
        num1[i].m=min(num1[i].a,num1[i].b);//先找到第i件中的A,B车间的最小的
    }
    sort(num1+1,num1+1+n,mycmp);
    int l=0,r=n+1;
    for(int i=1;i<=n;i++)
    {
        if(num1[i].m==num1[i].a)//此时最小值是A车间中的,应该放在队列的前面
            num2[++l]=num1[i];
        else
            num2[--r]=num1[i];//同理可得此时最小值是B车间中的,应该放在队列的后面
    }

②模拟求和
我觉得对于我来说,上面的排序并不是很大的问题,而真正的难题是最后收尾的求和
在这里以B车间为标准,(即若是求出来了B车间中的工作时间,那么就是这个过程中的工作时间)
见下图(针对于样例来说):
在这里插入图片描述
所以可以整体考虑,当A车间的整体的值大于B车间的值是,B车间的工作时间就要变成A车间的工作时间。
见部分代码:

    for(int i=1;i<=n;i++)
    {
        sum1+=num2[i].a;
        sum2=max(sum1,sum2)+num2[i].b;
    }

见全部代码如下:

#include<bits/stdc++.h>
using namespace std;
int n;
long long sum1=0,sum2=0;

struct number
{
    int id,a,b,m;
};
number num1[1010];
number num2[1010];

inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}

bool mycmp(number x,number y)
{
    return x.m<y.m;
}

int main()
{
    //freopen("1.in","r",stdin);
    n=read();
    for(int i=1;i<=n;i++)
    {
        num1[i].id=i;
        num1[i].a=read();
    }
    for(int i=1;i<=n;i++)
    {
        num1[i].b=read();
        num1[i].m=min(num1[i].a,num1[i].b);
    }
    sort(num1+1,num1+1+n,mycmp);
    int l=0,r=n+1;
    for(int i=1;i<=n;i++)
    {
        if(num1[i].m==num1[i].a)//此时应该放在队列的前面
            num2[++l]=num1[i];
        else
            num2[--r]=num1[i];
    }
    for(int i=1;i<=n;i++)
    {
        sum1+=num2[i].a;
        sum2=max(sum1,sum2)+num2[i].b;
    }
    printf("%lld\n",sum2);
    for(int i=1;i<=n;i++)
    {
        printf("%d ",num2[i].id);
    }
    return 0;
}

其实,上面的心路历程我也不知道写了些什么……
总之,2019肯定会更好的呀!!!!

猜你喜欢

转载自blog.csdn.net/qq_43093454/article/details/85118870