CCF-CSP题解(2019)

201903

201903-2 二十四点

可枚举。

写栈的主要思想是:一个数栈\(numSta\),一个运算符栈\(opSta\)。遇到一个运算符,就把之前优先级\(equal\ or\ greater\ than\)它的运算符处理掉。

#include <bits/stdc++.h>

using namespace std;

int operation(int num1, char op, int num2)
{
    if (op == '+')
        return num1 + num2;
    else if (op == '-')
        return num1 - num2;
    else if (op == 'x')
        return num1 * num2;
    else
        return num1 / num2;
}

int getAns(char s[]) {
    stack<int> numSta;
    stack<char> opSta;
    for (int i = 1; i <= 7; i++)
    {
        if (s[i] >= '1' && s[i] <= '9')
            numSta.push(s[i] - '0');
        else
        {
            if (s[i] == '+' || s[i] == '-')
            {
                while (!opSta.empty())
                {
                    char op = opSta.top(); opSta.pop();
                    int num2 = numSta.top(); numSta.pop();
                    int num1 = numSta.top(); numSta.pop();
                    numSta.push(operation(num1, op, num2));
                }
                opSta.push(s[i]);
            }
            else
            {
                while (!opSta.empty() && (opSta.top() == 'x' || opSta.top() == '/'))
                {
                    char op = opSta.top(); opSta.pop();
                    int num2 = numSta.top(); numSta.pop();
                    int num1 = numSta.top(); numSta.pop();
                    numSta.push(operation(num1, op, num2));
                }
                opSta.push(s[i]);
            }
        }
    }
    while (!opSta.empty())
    {
        char op = opSta.top(); opSta.pop();
        int num2 = numSta.top(); numSta.pop();
        int num1 = numSta.top(); numSta.pop();
        numSta.push(operation(num1, op, num2));
    }
    return numSta.top();
}

int main ()
{
    int n;
    scanf("%d", &n);

    while (n--)
    {
        char s[10];
        scanf("%s", s + 1);
        if (getAns(s) == 24)
            printf("Yes\n");
        else
            printf("No\n");
    }

    return 0;
}

201903-3 损坏的RAID5

先吐槽先吐槽!因为输入太大,需要用fgets,读n个字符或读到回车终止。

char *fgets(char *str, int n, FILE *stream)

因为scanf模拟考试T了10+次。因为IO超时的题目都是乐色!(x

用数组存磁盘信息。\(char [1000][40960*2]\)不会爆。静态数据区一般2G大小。

然后就是模拟。计算每个询问块号的条带号、单个磁盘条带号、磁盘号。分情况讨论。

%x小写16进制,%X大写。%d十,%o八,%b二。

#include <bits/stdc++.h>
const int maxn = 1000;
const int maxm = 40960;

using namespace std;

char disk[maxn+10][maxm*2+10];
int vis[maxn+10];
int len, got = 0;

int main()
{
    int n, s, l;
    scanf("%d%d%d", &n, &s, &l);

    memset(vis, 0, sizeof(vis));
    for (int i = 1, x; i <= l; i++)
    {
        scanf("%d ", &x);
        vis[x] = 1;
        fgets(disk[x], maxm*2 + 10, stdin);
        if (!got)
        {
            len = strlen(disk[x]) / 8 / s - 1;
            got = 1;
        }
    }

    int m;
    scanf("%d", &m);
    while (m--)
    {
        int b;
        scanf("%d", &b);
        int stripe = b / s;
        int k = stripe / (n-1);
        int diskNum = (n - k%n + stripe % (n-1)) % n;
        if (k > len || (n-l >= 2 && !vis[diskNum]))
        {
            printf("-\n");
        }
        else
        {
            int st = (k*s + b%s) * 8, en = st + 7;
            if (vis[diskNum])
            {
                for (int i = st; i <= en; i++)
                    printf("%c", disk[diskNum][i]);
                printf("\n");
            }
            else
            {
                for (int i = st; i <= en; i++)
                {
                    int ans = 0;
                    for (int j = 0, tmp; j <= n-1; j++)
                    {
                        if (j != diskNum)
                        {
                            if (disk[j][i] >= '0' && disk[j][i] <= '9')
                            {
                                tmp = disk[j][i] - '0';
                            }
                            else
                            {
                                tmp = disk[j][i] - 'A' + 10;
                            }
                            ans ^= tmp;
                        }
                    }
                    printf("%X", ans);
                }
                printf("\n");
            }
        }
    }

    return 0;
}

201903-4 消息传递接口

求并行的各个进程,且进程内部顺序执行的情况下,会不会出现“死锁”。

首先用\(%[^\n]\)将每个进程读入。最后过不了居然是因为\(str[\ ]\)开小了(悲喜交加。存储在\(<op,\ pid>[\ ]\)中,并记录每个进程的指令数\(instNum[\ ]\)

然后就是模拟。\(instCmp[\ ]\)记录每个进程已完成的指令数,\(instBlk[\ ]\)记录每个进程是否阻塞,\(numCmp,\ numBlk\)分别是完成和阻塞的进程数。主要思想是:每次执行到某条指令阻塞,然后执行下条指令并循环。判断是否阻塞,就是看\(<op, pid>\)对应的\(pid\)进程当前已完成的指令是否有下一条指令,以及下一条指令是否与之配对。

#include <bits/stdc++.h>
const int maxn = 10000;

using namespace std;

struct tInst
{
    int op;
    int pid;
};
tInst inst[maxn+10][10];
int instNum[maxn+10];

int instCmp[maxn+10];
int instBlk[maxn+10];
int numCmp, numBlk;

int main ()
{
    int T, n;
    scanf("%d%d", &T, &n);
    getchar();

    while (T--)
    {
        memset(instNum, 0, sizeof(instNum));
        for (int i = 0; i <= n - 1; i++)
        {
            char str[100];
            scanf("%[^\n]", str + 1);
            getchar();
            for (int j = 1, op = 0, pid = 0; ; j++)
            {
                if (str[j] == 'R')
                    op = 0;
                else if (str[j] == 'S')
                    op = 1;
                else if (str[j] >= '0' && str[j] <= '9')
                    pid = pid * 10 + str[j] - '0';
                else if (str[j] == ' ')
                {
                    inst[i][++instNum[i]].op = op;
                    inst[i][instNum[i]].pid = pid;
                    pid = 0;
                }
                else
                {
                    inst[i][++instNum[i]].op = op;
                    inst[i][instNum[i]].pid = pid;
                    break;
                }
            }
        }

        memset(instCmp, 0, sizeof(instCmp));
        memset(instBlk, 0, sizeof(instBlk));
        numCmp = numBlk = 0;

        int x = 0;
        while (numCmp + numBlk != n)
        {
            while (instCmp[x] != instNum[x] && !instBlk[x])
            {
                int y = instCmp[x] + 1;
                int op = inst[x][y].op, pid = inst[x][y].pid;
                int xx = pid;
                if (instCmp[xx] != instNum[xx])
                {
                    int yy = instCmp[xx] + 1;
                    if (op + inst[xx][yy].op == 1 && x == inst[xx][yy].pid)
                    {
                        instCmp[x] ++; instCmp[xx] ++;
                        if (instCmp[x] == instNum[x])
                            numCmp ++;
                        if (instCmp[xx] == instNum[xx])
                            numCmp ++;
                        if (instBlk[xx])
                        {
                            instBlk[xx] = 0;
                            numBlk --;
                        }
                    }
                    else
                    {
                        instBlk[x] = 1;
                        numBlk ++;
                    }
                }
                else
                {
                    instBlk[x] = 1;
                    numBlk ++;
                }
            }
            x = (x + 1) % n;
        }

        if (numCmp == n)
            printf("0\n");
        else
            printf("1\n");

    }

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/acboyty/p/11352280.html