列表

详情


NC231653. Liyuu的狂热粉丝的计算机

描述

Liyuu_的狂热粉丝设计了一台拥有两个输入设备(指令输入器和数据输入器)、一个输出设备、三种存储器、中央处理器(CPU)和一套可能是图灵完备的指令系统的计算机(以下简称计算机)。

简单地说,计算机的存储器分为指令和数据两类,其中指令内部存储器存储待执行的N条指令并且能记录将要执行到的是第几条指令。而数据存储器可存储32位有符号整数(int类型),其拥有个存储单元,其中前16个单元(索引从0到15)为寄存器,接下来的M个单元为数据内部存储器(以下简称数据内存),所有数据存储器单元的初始值均为0。所以存储器共有指令内部存储器、寄存器和数据内存三类。寄存器和数据内存是有区别的。特别的,寄存器的0号单元(数组的第0个位置)不能写入,其值恒为0.

在工作时,会先从读入N条指令,将它们按0到N-1编号,然后把将要执行到的指令记为0并开始执行。执行过程中,计算机每次读取将要执行到的指令,接着把将要执行到的指令加一,然后执行读取到的指令的功能。实际上计算机会在读取到所有指令后增加一条停机指令,其编号为N,当执行到它时,计算机会正常关机。计算机的指令的固定格式为`指令 整数 整数 整数`,其中的"整数"是该条指令的参数,不是所有参数都会被使用到

指令共有如下10种:

以下为一段指令使用示例:
in 65 56 45 mov 15 1 1 in 45 14 475 cmp 1 15 2 jz 0 4 4

这段指令会被依次编号为0,1,2,3,4,并且其结尾会有一条编号为5的停机指令。
0. 计算机先执行第0条指令,其结果是15号寄存器中存储了从数据输入器中读到的一个整数。
1. 计算机接着执行第1条指令,其结果是15号寄存器中的整数被存到了1号寄存器中。
2. 计算机接着执行第2条指令,其结果是15号寄存器中存储了从数据输入器中读到的一个整数。
3. 计算机接着执行第3条指令,当15号寄存器中的整数与1号寄存器中的整数相同时,14号寄存器会被改为1;当15号寄存器中的整数大于1号寄存器中的整数相同时,14号寄存器会被改为2;
4. 计算机接着执行第4条指令,如果14号寄存器的值不为1时,计算机会把将要执行到的指令记为0,否则不做任何事。所以接下来计算机可能会回到第0条指令开始执行,也可能按顺序执行第5条指令。
5. 计算机接着执行第5条指令,其结果是计算机正常关机。

执行这段指令时计算机会不停地读入两个整数,判断它们是否相等,如果不等,则停止运行。

执行一条指令前,计算机会判断指令参数是否合法,任何**非法**的指令均会导致计算机立即开始执行预定的异常退出模块,计算机会在输出设备上单独打印一行显示"error",然后终止运行。

为了测试已经制作完成的初号机,Liyuu_的狂热粉丝向你寻求帮助。

他会给你这个初号机的数据内存大小和一段他的测试程序,并给你一段将送入数据输入器的数据,而你需要给出正确的输出。

(两个out之间需要空格)

输入描述

输入的第一行包括两个整数表示有有N条指令和M个数据内存单元
接下来为N行,每一行一段指令,表示了将要执行的程序,保证所有指令均符合格式。
接着一行给出若干(可能没有)整数,表示Liyuu的狂热粉丝给机器的输入,初号机可能不会读取到所有输入,但保证初号机总是能读到整数。

输出描述

输出一行整数(可能没有),表示Liyuu的狂热粉丝的机器的输出。
如果机器运行遇到了非法情况,则换行输出"error"。

示例1

输入:

5 5
in 1 2 3
add 1 0 15
in 1 2 3
add 15 1 15
out 12 31 41
1 1

输出:

2

示例2

输入:

6 5
in 1 2 3
add 1 0 15
in 312 45 1
add 15 1 15
add 16 1 15
out 15 145 4
1 1

输出:

error

说明:

第一行是有一行空行,第二行为error,样例可能显示不正确。

示例3

输入:

7 10
in 1 2 3
mov 15 1 2
in 1 2 3
cmp 1 15 1
mov 14 15 1
out 1 2 3
jz 0 2 3
14 14 14 14 15 16

输出:

1 1 0

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 3ms, 内存消耗: 460K, 提交时间: 2022-09-07 13:55:07

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

std::vector<std::string> split(const std::string& s, std::string c = " ") {
    std::vector<std::string> ret;
    std::size_t pos1 = 0, pos2 = s.find(c);
    while (pos2 != std::string::npos) {
        ret.emplace_back(s.substr(pos1, pos2 - pos1));
        pos1 = pos2 + 1;
        pos2 = s.find(c, pos1);
    }
    if (pos1 != s.size()) ret.emplace_back(s.substr(pos1));
    ret.erase(std::remove_if(ret.begin(), ret.end(), [&s](const std::string& rhs) -> bool {
                return rhs.empty();
    }), ret.end());
    return ret;
}

int f = 0;
void ERR() {
    cout << endl;
    cout << "error" << endl;
    exit(0);
}
int main() {
    int n, m;
    cin >> n >> m;
    vector<tuple<string,int,int,int>> ops(n);
    for(auto &[s, a, b, c] : ops) {
        cin >> s >> a >> b >> c;
    }
    cin.get();
    string p;
    getline(cin, p);
    vector<int> inputs;
    if(!p.empty()) {
        vector<string> ps = split(p, " ");
        for(auto s : ps) {
            inputs.push_back(stoi(s));
        }
    }
    reverse(inputs.begin(), inputs.end());
    vector<int> mem(m + 16);
    for(int i = 0; i < n;) {
        auto [s, a, b, c] = ops[i];
        if(s == "in") {
            assert(!inputs.empty());
            mem[15] = inputs.back();
            inputs.pop_back();
        } else if(s == "out") {
            f = 1;
            cout << mem[15] << " ";
        } else if(s == "mov") {
            if(b == 0 || b >= mem.size() || a >= mem.size()) ERR();
            mem[b] = mem[a];
        } else if(s == "add") {
            if(1 <= a && a <= 15 && 0 <= b && b <= 15 && 0 <= c && c <= 15) {
            } else {
                ERR();
            }
            mem[a] = mem[b] + mem[c];
        } else if(s == "cmp") {
            if(0 <= a && a <= 15 && 0 <= b && b <= 15) {
            } else {
                ERR();
            }
            if(mem[a] == mem[b]) mem[14] = 1;
            else if(mem[a] > mem[b]) mem[14] = 2;
            else mem[14] = 0;
        } else if(s == "jz") {
            if(a > n) ERR();
            if(mem[14] == 1) {
                if(a == n) break;
                i = a;
                continue;
            }
        } else if(s == "jnz") {
            if(a > n) ERR();
            if(mem[14] != 1) {
                if(a == n) break;
                i = a;
                continue;
            }
        } else if(s == "jg") {
            if(a > n) ERR();
            if(mem[14] == 2) {
                if(a == n) break;
                i = a;
                continue;
            }
        } else {
            assert(0);
        }
        ++i;
    }
    return 0;
}

Python3 解法, 执行用时: 41ms, 内存消耗: 4840K, 提交时间: 2021-12-13 00:34:35

n,m = list(map(int,input().split(" ")))
inst = []
for _ in range(n):
    tmp = input().split(" ")
    for i in range(1,len(tmp)): tmp[i] = int(tmp[i])
    inst.append(tmp)
inp = list(map(int,input().split(" ")))
inp.reverse()
reg = [0] * 16
mem = [0] * m
outs = []

def solve():
    global inp,reg,mem,outs
    idx = 0
    getOp = lambda num: inst[idx][1:1+num] if num > 1 else inst[idx][1]
    ob0 = lambda v: not (0 <= v and v <= 15)
    ob1 = lambda v: not (1 <= v and v <= 15)
    while idx < n:
        if inst[idx][0] == "in":
            reg[15] = inp.pop()
        elif inst[idx][0] == "out":
            outs.append(reg[15])
        elif inst[idx][0] == "mov":
            a,b = getOp(2)
            if a < 0 or b <= 0: return False
            try:
                val = reg[a] if a < 16 else mem[a-16]
                if b >= 16: mem[b-16] = val
                else: reg[b] = val
            except IndexError:
                return False
        elif inst[idx][0] == "add":
            a,b,c = getOp(3)
            if ob1(a) or ob0(b) or ob0(c): return False
            reg[a] = reg[b] + reg[c]
        elif inst[idx][0] == "cmp":
            a,b = getOp(2)
            if ob0(a) or ob0(b): return False
            reg[14] = 1 if reg[a] == reg[b] else (2 if reg[a] > reg[b] else 0)
        elif inst[idx][0] == "jz":
            a = getOp(1)
            if a < 0 or a > n: return False
            if reg[14] == 1:
                idx = a-1
        elif inst[idx][0] == "jnz":
            a = getOp(1)
            if a < 0 or a > n: return False
            if reg[14] != 1:
                idx = a-1
        elif inst[idx][0] == "jg":
            a = getOp(1)
            if a < 0 or a > n: return False
            if reg[14] == 2:
                idx = a-1
        else: return False
        idx += 1
    return True

fl = solve()
print(*outs)
if not fl: print("error")

C++ 解法, 执行用时: 4ms, 内存消耗: 476K, 提交时间: 2021-12-12 14:04:19

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int n,m;
string str[N];
int p[N][3];
int reg[N];
inline bool check_reg1(int x)
{
    return x>0&&x<16;
}
inline bool check_reg0(int x)
{
    return x>=0&&x<16;
}
inline bool check_mem(int x)
{
    return x>15&&x<16+m;
}
inline int err()
{
    puts("");
    puts("error");
    exit(0);
}
inline int cmp(int x,int y)
{
    if(x==y)
        return 1;
    if(x>y)
        return 2;
    return 0;
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
        cin>>str[i]>>p[i][0]>>p[i][1]>>p[i][2];
    int i=0,x;
    while(i<n)
    {
        if(str[i]=="in")
            cin>>reg[15];
        else if(str[i]=="out")
            cout<<reg[15]<<' ';
        else if(str[i]=="mov"&&(check_reg1(p[i][0])||check_mem(p[i][0]))
                            &&(check_reg1(p[i][1])||check_mem(p[i][1])))
            reg[p[i][1]]=reg[p[i][0]];
        else if(str[i]=="add"&&check_reg1(p[i][0])&&check_reg0(p[i][1])&&check_reg0(p[i][2]))
            reg[p[i][0]]=reg[p[i][1]]+reg[p[i][2]];
        else if(str[i]=="cmp"&&check_reg0(p[i][0])&&check_reg0(p[i][1]))
            reg[14]=cmp(reg[p[i][0]],reg[p[i][1]]);
        else if(str[i]=="jz"&&(p[i][0]<n||(p[i][0]==n)&&i==n-1))
            i=reg[14]==1?p[i][0]-1:i;
        else if(str[i]=="jnz"&&(p[i][0]<n||(p[i][0]==n)&&i==n-1))
            i=reg[14]!=1?p[i][0]-1:i;
        else if(str[i]=="jg"&&(p[i][0]<n||(p[i][0]==n)&&i==n-1))
            i=reg[14]==2?p[i][0]-1:i;
        else err();
        i++;
    }
    return 0;
}

上一题