• P1065 [NOIP2006 提高组] 作业调度方案


    题目传送门

    #include <bits/stdc++.h>
    
    using namespace std;
    const int N = 20 + 10; //m<20,n<20,范围是20以内,开大一点防止出错
    
    //本题,不吸氧,可以过10个点,第11个点TLE。吸氧后可以能完全部11个点。
    
    //用来记录题目输入的数据信息
    int n, m;               //m表示机器数,n表示工件数
    int seq[N * N];         //为给定的安排顺序。大小为m*n,所以开了一个N*N的数组。是安排顺序的简写形式。
    int p[N][N];            //工件+工序的机器号
    int t[N][N];            //工件+工序的执行时长
    
    const int M = N * N * 100; //时长最长情况的上限,比如n个工件,全都安排在1号机器上制作,共m个工序,每个工序时长为1000,咋也够了吧?
    int res[N][M];              //这是每台机器的时长安排情况,记录每台机器上每个时间点是哪个工件在制作
    
    //获取第i个位置的数据,是seq[i]这台机器的第几次出现?
    int getProcessNum(int i) {
        int x = seq[i];
        int cnt = 0;
        for (int j = 0; j <= i; j++)if (seq[j] == x) cnt++;
        return cnt;
    }
    
    //获取工件x的最后制作时间
    int getLastTime(int x) {
        int lastTime = 0;
        for (int i = 1; i <= m; i++)// 遍历所有机器
            for (int j = M - 1; j >= 0; j--)
                if (res[i][j] == x) {
                    lastTime = max(lastTime, j + 1);//找出最大值,就是最后的制作时间
                    break;
                }
        return lastTime;
    }
    
    
    /**
     * 功能:检查函数
     * @param start 从哪个时间开始
     * @param len   需要多长的时间
     * @param mac   哪台机器上进行检查
     * @return      是不是能放得下去
     */
    bool check(int start, int len, int mac) {
        for (int i = start; i < start + len; i++)
            if (res[mac][i])return false; //在这个范围内,如果有使用的情况,就返回false, 表示放不下去
        //全部通过,表示可以放的下去,返回true
        return true;
    }
    
    int main() {
        //m机器数,n工件数
        //示例数据:2 3,表示2台机器,3个工件
        cin >> m >> n;
    
        //给定的安排顺序,示例数据:1 1 2 3 3 2,描述第一个物品第一个工序,第一个物品第二个工序,第二个物品第一个工序,第三个物品第一个工序,第三个物品第二个工序,第二个物品第二个工序
        for (int i = 1; i <= n * m; i++) cin >> seq[i];
    
        /**
        前n行依次表示每个工件的每个工序所使用的机器号,第1个数为第1个工序的机器号,第2个数为第2个工序机器号,等等。
        1 2   第一件物品,第1个工序需要在1号机器上进行,第2个工序需要在2号机器上进行
        1 2   第二件物品,第1个工序需要在1号机器上进行,第2个工序需要在2号机器上进行
        2 1   第三件物品,第1个工序需要在2号机器上进行,第2个工序需要在1号机器上进行
        */
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
                cin >> p[i][j];
    
        //每个工件的每个工序的加工时间
        //后n行依次表示每个工件的每个工序的加工时间。
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
                cin >> t[i][j];
    
        //处理每一个输入顺序
        for (int i = 1; i <= n * m; i++) {
            int x = seq[i];                      //第几个工件
            int y = getProcessNum(i);            //此工件的第几个工序(第几次出现就是第几个工序)
            int mac = p[x][y];                   //根据工件+工件的工序--->第几个机器上加工
    
            for (int j = getLastTime(x);; j++) { //此工件需要在最后一次加工时间的基础上去尝试,符合规则1,直到找到答案为止
                //看看有空的话,能不能放的下去,比如有3个空,但不够长,就不行
                if (check(j, t[x][y], mac)) {
                    //标识此位置被占用
                    for (int k = j; k < j + t[x][y]; k++)res[mac][k] = x;
                    break;
                }
            }
        }
    
        //找到最长的时间是哪个
        int ans = 0;
        for (int i = 1; i <= n; i++)ans = max(ans, getLastTime(i));
        cout << ans << endl;
        return 0;
    }
    

    //P1065_2.cpp

    #include <bits/stdc++.h>
    
    using namespace std;
    const int N = 20 + 10; //m<20,n<20,范围是20以内,开大一点防止出错
    
    //题意解析
    //https://www.bilibili.com/video/BV14K411J7Hr?from=search&seid=5350204733209198842
    //手绘图形进行样例解析说明,让学生们手工绘制帮助理解题意。
    //用来记录题目输入的数据信息
    int n, m;               //m表示机器数,n表示工件数
    int seq[N * N];         //为给定的安排顺序。大小为m*n,所以开了一个N*N的数组。是安排顺序的简写形式。
    //举个例子: 112332 表示第一个工件第一道工序,第一个工件第二道工序,第二个工件第1个工序....
    
    int p[N][N];           //工件+工序的机器号
    int t[N][N];            //工件+工序的执行时长
    
    //下面是程序开发中需要的中间变量
    int cnt[N];             //用来存储遍历到了当前工件的第几个工序
    //Q:为什么要用数组来存储是第几个工序?
    //A:因为有多个工件,每一个工件都随时需要知道它现在再次出现的是第几个工序了,需要有地方可以查询到,这里使用了桶排的思想。
    
    int last[N];            //记录每份工件的最后一次加工时间
    //Q:为什么要记录最后一次的加工时间?
    //A:因为每个工件,它的加工顺序是不能反的,也就是规则1,如何才能不违反规则1呢?就是记录下它的最后一次执行时间,然后把下一个工序安排在最后一次执行时间后面就行了。
    
    int res[N][N * N * 100];    //标识每台机器的时间使用情况,第一维:机器,第二维:时间,值:是不是占用了
    
    /**
     * 功能:检查函数
     * @param start 从哪个时间开始
     * @param len   需要多长的时间
     * @param mac   哪台机器上进行检查
     * @return      是不是能放得下去
     */
    bool check(int start, int len, int mac) {
        for (int i = start; i < start + len; i++)
            if (res[mac][i])return false; //在这个范围内,如果有使用的情况,就返回false, 表示放不下去
        //全部通过,表示可以放的下去,返回true
        return true;
    }
    
    int main() {
        //m机器数,n工件数
        //示例数据:2 3,表示2台机器,3个工件
        cin >> m >> n;
    
        //给定的安排顺序,示例数据:1 1 2 3 3 2,描述第一个物品第一个工序,第一个物品第二个工序,第二个物品第一个工序,第三个物品第一个工序,第三个物品第二个工序,第二个物品第二个工序
        for (int i = 1; i <= n * m; i++) cin >> seq[i];
    
        /**
        前n行依次表示每个工件的每个工序所使用的机器号,第1个数为第1个工序的机器号,第2个数为第2个工序机器号,等等。
        1 2   第一件物品,第1个工序需要在1号机器上进行,第2个工序需要在2号机器上进行
        1 2   第二件物品,第1个工序需要在1号机器上进行,第2个工序需要在2号机器上进行
        2 1   第三件物品,第1个工序需要在2号机器上进行,第2个工序需要在1号机器上进行
        */
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
                cin >> p[i][j];
    
        //每个工件的每个工序的加工时间
        //后n行依次表示每个工件的每个工序的加工时间。
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
                cin >> t[i][j];
    
        //找到最长的时间是哪个
        int ans = 0;
    
        //处理每一个输入顺序
        for (int i = 1; i <= n * m; i++) {
            //利用桶排思路,记录每个工件的加工到第几个工序
            cnt[seq[i]]++;
    
            int x = seq[i];                 //第几个工件
            int y = cnt[seq[i]];            //此工件的第几个工序(第几次出现)
            int mac = p[x][y];              //根据工件+工件的工序--->第几个机器上加工
    
            for (int j = last[x];; j++) { //此工件需要在最后一次加工时间的基础上去尝试,符合规则1,直到找到答案为止
                //看看有空的话,能不能放的下去,比如有3个空,但不够长,就不行
                if (check(j, t[x][y], mac)) {
                    //标识此位置被占用
                    for (int k = j; k < j + t[x][y]; k++)res[mac][k] = x;
                    //更新最后的位置值
                    last[x] = j + t[x][y];
                    //不断的更新最大值
                    ans = max(ans, last[x]);
                    break;
                }
            }
        }
        cout << ans << endl;
        return 0;
    }
    
  • 相关阅读:
    CentOS 7 firewalld vsftpd开放端口
    sqlalchemy操作----多表关联
    sqlalchemy 或者pysql 连接数据库时支持中文操作
    sqlalchemy操作----外键关联,relationship
    sqlalchemy操作----建表 插入 查询 删除
    python 操作mysql
    指针和二维数组的关系要点简单分析
    二维数组基本操作练习题
    单独取出整数的个位,十位,百位,以及素数的小综合题
    LeetCode | Add Two Numbers II
  • 原文地址:https://www.cnblogs.com/littlehb/p/15588876.html
Copyright © 2020-2023  润新知