1. 程式人生 > >加工生產排程

加工生產排程

在這裡插入圖片描述
在這裡插入圖片描述

心路歷程(如果你沒有時間請直接跳到下一板塊(。・_・)/~~~)

針對於這道題,一開始博主並不知道也沒有用所謂的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肯定會更好的呀!!!!