入门经典_Chap06_例题[一]:队列,栈,链表的数组实现

来源:互联网 发布:淘宝数据分析哪些内容 编辑:程序博客网 时间:2024/06/05 18:39

前言

    这一章的终极目的是巩固数据结构,尽可能地使用数组实现所有的数据结构,包括队列,栈,链表,二叉树等

题解如下

UVA - 210_Concurrency Simulator

思路

    (书上的原话)你的任务是模拟n个程序(按输入顺序编号为1~n)的并行执行。每个程序包含不超过25条语句,格式一共有5种:var = constant(赋值);print var(打印);lock;unlock;end。
    变量用单个小写字母表示,初始为0,为所有程序公有(因此在一个程序里对某个变量赋值可能会影响另一个程序)。常数是小于100的非负整数。
    每个时刻只能有一个程序处于运行态,其他程序均处于等待态。上述5种语句分别需要t1、t2、t3、t4、t5单位时间。运行态的程序每次最多运行Q个单位时间(称为配额)。当一个程序的配额用完之后,把当前语句(如果存在)执行完之后该程序会被插入一个等待队列中,然后处理器从队首取出一个程序继续执行。初始等待队列包含按输入顺序排列的各个程序,但由于lock/unlock语句的出现,这个顺序可能会改变。
    lock的作用是申请对所有变量的独占访问。lock和unlock总是成对出现,并且不会嵌套。lock总是在unlock的前面。当一个程序成功执行完lock指令之后,其他程序一旦试图执行lock指令,就会马上被放到一个所谓的阻止队列的尾部(没有用完的配额就浪费了)。当unlock执行完毕后,阻止队列的第一个程序进入等待队列的首部。输入n, t1, t2, t3, t4, t5, Q以及n个程序,按照时间顺序输出所有print语句的程序编号和结果。

    使用队列模拟,要用到双端队列,这里用数组模拟的, 也可以使用STL里的deque
    复杂点在于字符串的处理,和lock的处理

代码

#include <algorithm>#include <iostream>#include <sstream>#include <utility>#include <string>#include <vector>#include <queue>#include <map>#include <set>#include <cstring>#include <cstdio>#include <cmath>#define met(a,b) memset(a, b, sizeof(a));#define IN freopen("in.txt", "r", stdin);using namespace std;typedef long long LL;typedef pair<int, int> PII;const int maxn = 1e3 + 100;const int INF = 0x7fffffff;int n, a[6], Q;string s, str;vector<string> v[maxn];int curID[maxn], val[30];bool lock;int qw[maxn], wft, wrr;int qd[maxn], dft, drr;int main() {    #ifdef _LOCAL    IN;    #endif // _LOCAL    int t; cin >> t;    while(t--) {        wft = wrr = maxn/2; dft = drr = maxn/2;        scanf("%d", &n); for(int i = 0; i < 5; ++i) scanf("%d", &a[i]); scanf("%d", &Q);        for(int i = 1; i <= n; ++i) {            v[i].clear();            while(getline(cin, s)) {                if(s == "") continue;                v[i].push_back(s);                if(s == "end") break;            }            qw[wrr++] = i;        }        met(curID, 0); met(val, 0); lock = 0;        while(wrr > wft) {            int cur = qw[wft++];            int L = Q, tot = v[cur].size();            bool flag = 0;            while(L > 0) {                str = v[cur][curID[cur]];                if(str[2] == '=') {                    str[2] = ' ';                    stringstream ss(str);                    char aa; int b;                    ss >> aa >> b;                    val[aa - 'a'] = b;                    L -= a[0];                }                else if(str[0] == 'p') {                    printf("%d: %d\n", cur, val[str[str.size()-1]-'a']);                    L -= a[1];                }                else if(str[0] == 'l') {                    if(lock) {                        qd[drr++] = cur; flag = 1; break;                    }                    lock = 1;                    L -= a[2];                }                else if(str[0] == 'u') {                    if(lock) {                        if(drr>dft) qw[--wft] = qd[dft++];                        lock = 0;                    }                    L -= a[3];                }                else { flag = 1; break; }                ++curID[cur];            }            if(! flag) qw[wrr++] = cur;        }        if(t) printf("\n");    }    return 0;}

UVA - 514_ Rails

思路

模拟栈的水题,不解释

代码

#include <algorithm>#include <iostream>#include <sstream>#include <utility>#include <string>#include <vector>#include <queue>#include <map>#include <set>#include <cstring>#include <cstdio>#include <cmath>#define met(a,b) memset(a, b, sizeof(a));#define IN freopen("in.txt", "r", stdin);using namespace std;typedef long long LL;typedef pair<int, int> PII;const int maxn = 1e3 + 100;const int INF = 0x7fffffff;int n, a[maxn];int stake[maxn];int main() {    #ifdef _LOCAL    IN;    #endif // _LOCAL    while(scanf("%d", &n) == 1 && n) {        while(scanf("%d", &a[0]) == 1 && a[0]) {            for(int i = 1; i < n; ++i) scanf("%d", &a[i]);            int cur = 1, top = 0;            bool ok = 1;            for(int i = 0; i < n; ++i) {                if(top > 0 && a[i] == stake[top]) {                    --top; continue;                }                else {                    while(cur <= n && a[i] != cur) stake[++top] = cur, ++cur;                    if(cur > n) { ok = 0; break; }                    else ++cur;                }            }            if(ok) printf("Yes\n");            else printf("No\n");        }        printf("\n");    }    return 0;}

UVA - 442_Matrix Chain Multiplication

思路

    输入n个矩阵的维度和一些矩阵链乘表达式,输出乘法的次数。如果乘法无法进行,输出error。
    假定A是m * n矩阵,B是n * p矩阵,那么AB是m * p矩阵,乘法次数为m * n * p。如果A的列数不等于B的行数,则乘法无法进行。
    例如,A是50 * 10的,B是10 * 20的,C是20 * 5的,则(A(BC))的乘法次数为10 * 20 * 5(BC的乘法次数)+ 50 * 10 * 5((A(BC))的乘法次数)= 3500。

    栈的应用:栈可以用于解析表达式!

代码

#include <algorithm>#include <iostream>#include <sstream>#include <utility>#include <string>#include <vector>#include <queue>#include <stack>#include <map>#include <set>#include <cstring>#include <cstdio>#include <cmath>#define met(a,b) memset(a, b, sizeof(a));#define IN freopen("in.txt", "r", stdin);using namespace std;typedef long long LL;typedef pair<int, int> PII;const int maxn = 1e3 + 100;const int INF = 0x7fffffff;int n, a, b;char c;string str;struct node {    int r, c;    node (){}    node (int a, int b):r(a), c(b){}}e[30];stack<node> s;int main() {    #ifdef _LOCAL    IN;    #endif // _LOCAL    cin >> n;    for(int i = 0; i < n; ++i) {        getchar();        scanf("%c %d%d", &c, &a, &b);        e[c-'A'] = node(a, b);    }    while(cin >> str) {        int len = str.length(), ans = 0;        for(int i = 0; i < len; ++i) {            if(str[i] == '(') { }            else if(str[i] == ')' ) {                node ta = s.top(); s.pop();                node tb = s.top(); s.pop();                if(ta.r != tb.c) { ans = -1; break; }                ans += tb.r*ta.r*ta.c;                s.push(node(tb.r, ta.c));            }            else s.push(e[str[i]-'A']);        }        if(ans == -1) printf("error\n");        else printf("%d\n", ans);    }    return 0;}

UVA - 11988_Broken Keyboard (a.k.a. Beiju Text)

思路

    链表的数组实现,实用+方便
    有一点个人领悟,使用链表的时候所有的数组最好下标都从1开始,给头指针留有余地。

代码

#include <algorithm>#include <iostream>#include <sstream>#include <utility>#include <string>#include <vector>#include <queue>#include <map>#include <set>#include <cstring>#include <cstdio>#include <cmath>#define met(a,b) memset(a, b, sizeof(a));#define IN freopen("in.txt", "r", stdin);using namespace std;typedef long long LL;typedef pair<int, int> PII;const int maxn = 1e6 + 100;const int INF = 0x7fffffff;char s[maxn];int nxt[maxn];int main() {    #ifdef _LOCAL    IN;    #endif // _LOCAL    while(cin >> s+1) {        nxt[0] = 0;        int cur = 0, last = 0;        int len = strlen(s+1);        for(int i = 1; i <= len; ++i) {            char c = s[i];            if(c == '[') cur = 0;            else if(c == ']') cur = last;            else {                nxt[i] = nxt[cur];                nxt[cur] = i;                if(cur == last) last = i;                cur = i;            }        }        for(int i = nxt[0]; i != 0; i = nxt[i]) printf("%c", s[i]);        printf("\n");    }    return 0;}

UVA - 12657_Boxes in a Line

思路

    双向链表的裸题,不过我写这道题的时候感觉蛮坑的
    主要是遍历的时候,最好根据元素个数来遍历,不要像单链表那样直接使用i = next[i]来遍历,因为它有一个循环的过程,搞不好会超时。
    然后在插入或者删除的时候,最好将会改变的东西先存下来,以防后面改其它的东西的时候它也跟着变了
    还有重要的一点,交换的时候两个物品相邻的情况要特判一下,不要想当然。

代码

#include <algorithm>#include <iostream>#include <sstream>#include <utility>#include <string>#include <vector>#include <queue>#include <map>#include <set>#include <cstring>#include <cstdio>#include <cmath>#define met(a,b) memset(a, b, sizeof(a));#define IN freopen("in.txt", "r", stdin);using namespace std;typedef long long LL;typedef pair<int, int> PII;const int maxn = 1e5 + 100;const int INF = 0x7fffffff;int n, m, x, y, opt;int nxt[maxn], pre[maxn];bool isRev;void combine(int i, int j) {    if(i == j) return;    nxt[i] = j; pre[j] = i;}void init() {    for(int i = 0; i <= n; ++i) combine(i, (i+1) % (n+1));}int main() {    #ifdef _LOCAL    IN;    #endif // _LOCAL    int kase = 0;    while(scanf("%d%d", &n, &m) == 2) {        init(); isRev = 0;        for(int i = 0; i < m; ++i) {            scanf("%d", &opt);            if(opt == 4) isRev = !isRev;            else {                scanf("%d%d", &x, &y);                if(opt != 3 && isRev) opt = 3 - opt;                int Px = pre[x], Nx = nxt[x];                int Py = pre[y], Ny = nxt[y];                if(opt == 1) {                    if(x == Py) continue;                    combine(Px,Nx); combine(Py, x); combine(x, y);                }                else if(opt == 2) {                    if(x == Ny) continue;                    combine(Px, Nx); combine(y, x); combine(x, Ny);                }                else {                    if(x == Ny) swap(x, y);                    Px = pre[x], Nx = nxt[x];                    Py = pre[y], Ny = nxt[y];                    if(y == Nx) {combine(Px, y); combine(y, x); combine(x, Ny); }                    else { combine(Px, y); combine(y,Nx); combine(Py, x); combine(x, Ny);}                }            }        }        LL ans = 0;        int b = 0;        for(int i = 1; i <= n; ++i) {            b = nxt[b];            if(i%2) ans += b;        }        if(isRev && n % 2 == 0) ans = (LL)n*(n+1)/2 - ans;        printf("Case %d: %lld\n", ++kase, ans);    }    return 0;}
阅读全文
0 0