【题目】LuoguP1065

准备机试,做两道题复健(这事我是不是干了好多次了)。

https://www.luogu.com.cn/problem/P1065

题意是有n个工件,每个工件有m道工序,每个工件的每道工序有其用时,同时对应一台机器,机器总共也有m台。每台机器同时只能处理一个工序。现给出工件的工序顺序,问尽可能靠前安排,所用的时间。

 

一种显然的做法是把时间像桶一样存起来,每安排一个工序就把一个区间格式化为占用。然后每次从开头开始查找。

但是要我说,这么做能过是因为数据不给力。比如,如果某工序需要2^31-1时间的话就不行了。

注意到工件和工序数量相对较少,所以可以用存区间+排序的方法做。具体思路是,对于每台机器创建一个区间列表来表示占用了的区间,添加新区间时就查找区间之间的间隔是否有足够大的,如果有就靠前插入。另外由于同一个工件的工序有前后之分,所以还需要一个数组来记录上一个工序的最后完成时间,和查找范围的左侧取最值。

一个小trick是存储区间的时候在头和尾多存储两个,头的右边界是0,尾的左边界是无穷,这样不需要额外的边界判断逻辑。

AC代码:

#include <iostream>
#include <cstdio>
#include <utility>
#include <algorithm>

#define fr first 
#define se second  

using namespace std;

const int MAXN = 22;//product
const int MAXM = 22;//process

pair<int,int> info[MAXN][MAXM];//machine, time use 

int order[MAXN*MAXM];
int m,n;

int lastpos[MAXN];
int step[MAXN];
pair<int,int> bsy[MAXM][MAXN*MAXM];
int cnt[MAXM];
int ntime;

bool cmp(pair<int,int> a, pair<int,int> b){
    return a.fr < b.fr;
}

int _max(int a,int b){
    return a>b?a:b;
}


int main(){
    //freopen("./p1065.in","r",stdin);
    //freopen("./p1065.out","w",stdout);


    cin>>m>>n;
    for(int i = 1; i <= n*m ; i++)
        cin>>order[i];
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= m ; j++)
            cin>>info[i][j].first;

    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= m ; j++)
            cin>>info[i][j].second;

    for(int i = 1; i <= m ; i++){
        bsy[i][1].fr = 0x7fffff;
        cnt[i] = 1;
    }
    
    int mx = 0;

    for(int iii = 1; iii <= n*m ; iii++){
        int nowpro = order[iii];
        int nowstep = step[nowpro]+1;
        int nowmac = info[nowpro][nowstep].fr;
        int nowtime = info[nowpro][nowstep].se;
        
        for(int i = 1; i <= cnt[nowmac]; i++){
            int rig = _max(bsy[nowmac][i-1].se, lastpos[nowpro]);
            if(bsy[nowmac][i].fr - rig - 1 >= nowtime){
                bsy[nowmac][cnt[nowmac]].fr = rig + 1;
                bsy[nowmac][cnt[nowmac]].se = rig + nowtime;
                lastpos[nowpro] = bsy[nowmac][cnt[nowmac]].se;
                //printf("新的%d的最后位置为%d \n",nowpro, lastpos[nowpro]);
                if(bsy[nowmac][cnt[nowmac]].se > mx) mx = bsy[nowmac][cnt[nowmac]].se;
                //printf("add:machine:%d,product:%d,count:%d,%d-%d\n",nowmac,nowpro,cnt[nowmac],bsy[nowmac][cnt[nowmac]].fr,bsy[nowmac][cnt[nowmac]].se);
                bsy[nowmac][++cnt[nowmac]].fr = 0x7fffff;
                step[nowpro] ++;
                break;
            }
        }

        sort(bsy[nowmac]+1, bsy[nowmac] + cnt[nowmac], cmp);

    }
    
    cout<<mx<<endl;

    return 0;
}
View Code

 

posted @ 2024-02-28 09:30  dudujerry  阅读(5)  评论(0编辑  收藏  举报