并行程序模拟Uva 210

这个题满满的都是套路。其实根本不难,就是一个双向队列的问题。如果你只看了紫书的话,那么你完蛋了,因为这个紫书数条件给的不够。你需要去看原题,并且要把它完整地翻译过来。

  • 这个题是有多个输入的,这个一般中文翻译都没有,需要去看原题。

  • 时间片用完之后,如果正在执行语句,那么这个语句将继续执行下去,哪怕最后时间为负数。并不是说时间一到就不执行了

  • 输入的时候首先要告诉你有几个输入,随后空一行。然后开始正式的一个输入块;输入块完成后,再空一行开始另一个输入块,循环往复。

  • 输出时每个输入块对应一个输出块,然后空一行再开始另一个输出块。最后一个输出块不用空最后一行。

思路

按照操作系统的做法:设计一个就绪队列,一个阻塞队列还有一个运行队列。在使用Java的双端队列API,整个题就非常的简单了。

package com.ahyer;

import java.util.*;

public class Main {
    static List<Program> list = new ArrayList<>();
    static Deque<Program> runState = new LinkedList<>();
    static Deque<Program> prepareState = new LinkedList<>();
    static Deque<Program> blockState = new LinkedList<>();
    static Map<String, String> map = new HashMap<>();
    static boolean block = false;

    static class Program {
        Deque<Statement> deque = new ArrayDeque<>();
        int programID;
    }

    static class Statement {
        String statement;
        int remain;
        int id;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.nextLine();
        int per = Integer.parseInt(s);
        while (per-- != 0) {
            list.clear();
            blockState.clear();
            runState.clear();
            prepareState.clear();
            map.clear();
            scanner.nextLine();
            String s1 = scanner.nextLine();
            String[] s2 = s1.split(" ");
            int program = Integer.parseInt(s2[0]);
            int t1 = Integer.parseInt(s2[1]);
            int t2 = Integer.parseInt(s2[2]);
            int t3 = Integer.parseInt(s2[3]);
            int t4 = Integer.parseInt(s2[4]);
            int t5 = Integer.parseInt(s2[5]);
            int Q = Integer.parseInt(s2[6]);
            for (int i = 0; i < program; i++) {
                list.add(new Program());
            }
            int programeNums = 0;

            while (programeNums != program) {
                String s3 = scanner.nextLine();
                if (s3.equals("")) break;
                Statement statement = new Statement();
                list.get(programeNums).deque.addLast(statement);
                list.get(programeNums).programID = programeNums + 1;
                statement.statement = s3;
                if (s3.contains("=")) {
                    statement.id = 1;
                    statement.remain = t1;
                } else if (s3.contains("print")) {
                    statement.id = 2;
                    statement.remain = t2;
                } else if (s3.equals("lock")) {
                    statement.remain = t3;
                    statement.id = 3;
                } else if (s3.equals("unlock")) {
                    statement.remain = t4;
                    statement.id = 4;
                } else {
                    statement.remain = t5;
                    statement.id = 5;
                    prepareState.addLast(list.get(programeNums++));
                }
            }
            //输入完成了

            while (!prepareState.isEmpty() || !blockState.isEmpty() || !runState.isEmpty()) {
                if (!prepareState.isEmpty()) {
                    runState.addFirst(prepareState.removeFirst());
                }
                Program runProgram = runState.getFirst();
                int time = Q;
                while (time > 0) {
                    int remain = runProgram.deque.getFirst().remain;
                    if (solve(runProgram)) {
                        break;
                    }
                    time -= remain;
                }
                if (!runState.isEmpty()) {
                    prepareState.addLast(runState.removeFirst());
                }
            }
            if (per != 0) {
                System.out.println();
            }
        }
    }

    private static boolean solve(Program runProgram) {
        String statement = runProgram.deque.getFirst().statement;
        String[] split = null;
        //程序代码序列
        if (runProgram.deque.getFirst().id == 3 && block) {
            blockState.addLast(runState.removeFirst());
            return true;
        }
        switch (runProgram.deque.removeFirst().id) {
            case 1:
                split = statement.split(" ");
                map.put(split[0], split[2]);
                break;
            case 2:
                split = statement.split(" ");
                if (map.get(split[1]) == null) {
                    map.put(split[1], "0");
                }
                System.out.println(runProgram.programID + ": " + map.get(split[1]));
                break;
            case 3:
                block = true;
                break;
            case 4:
                block = false;
                if (!blockState.isEmpty()) {
                    prepareState.addFirst(blockState.removeFirst());
                }
                break;
            case 5:
                //本程序结束了
                runState.removeFirst();
                return true;
            default:
                break;
        }
        return false;
    }
}

这个双端队列的API。最好分开写,因为如果单独写的话,如果这个队列只有一个元素,那么你连着写remove()掉再addLast()那就相当于没有变。上面这个代码不存在这种问题,因为操作多个队列。

原文地址:https://www.cnblogs.com/HyPhoenix/p/14407377.html