//快期末了,挺忙的,打算把第六章的内容从新再复习一遍了,很多细节的地方还没掌握。
栈: 满足后进先出,C++中可以用 STL 中的 stack 来构造。
构造方法为:stack<数据类型> 栈名字。top() 取栈顶元素,pop() 栈顶出栈,push(元素) 将元素压入栈。
队列: 满足先进先出,C++中可用 STL 中的 queue 来构造(deque 可以用来构造双端队列)。
构造方法同栈,front() 取队首元素(双端队列中可用 back() 取队末元素),pop() 队首出栈(双端队列中为 pop_front()、pop_back()),push(元素) 将元素加入队列(双端队列中为 push_front()、push_back())。
例题 6-1 UVa 210
题目:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=838&page=show_problem&problem=146
思路:模拟执行即可,先写出伪代码再编程。
while(等待队列中还有程序){
while(还有配额){
if(执行完这条语句就没有配额了) 换下一个程序,将此程序放到队末
if(这条语句是 lock){
if(当前处于锁定状态) 将此程序加入阻止队列,换下一个程序
if(当前不处于锁定状态) 将状态改为锁定状态
}
这条语句一定执行了,将配额减少
if(是赋值语句) 进行赋值
if(是输出语句) 进行输出
if(是 unlock 语句){
将状态改为非锁定状态
if(阻止队列中还有程序) 将阻止队列队首的程序放到等待队列队首。
}
}
}
注意:只要还有配额,程序就可以运行。程序的配额在运行完以后可以是负的,但一旦没有配额了,就换下一个程序。开先做的时候以为只要剩下的配额不够运行了就要切换到下一个程序,结果超时了好几次。
代码:
/* Concurrency Simulator (UVa 210) */ #include <iostream> #include <queue> #include <deque> #include <cstring> #include <sstream> using namespace std; struct Program{ int number; //编号 queue<string> code; //若干条语句 Program(int number): number(number){} }; int main(){ //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); int T; cin >> T; while(T--){ int n, t1, t2, t3, t4, t5, q; int ch[30]; //变量 int toTime[130]; //将命令转换成时间 deque<Program> wait; //等待队列 queue<Program> stop; //阻止队列 bool isLock = false; //是否处于 Lock 状态 memset(ch, 0, sizeof(ch)); cin >> n >> t1 >> t2 >> t3 >> t4 >> t5 >> q; getchar(); toTime['='] = t1; toTime['i'] = t2; toTime['c'] = t3; toTime['l'] = t4; toTime['d'] = t5; for(int i=1; i<=n; i++){ //输入 string s; Program program(i); while(1){ getline(cin, s); program.code.push(s); if(s == "end") break; } wait.push_back(program); } while(!wait.empty()){ //模拟运行 Program program = wait.front(); wait.pop_front(); //取等待队列队首程序 int t = q; while(!program.code.empty()){ string s = program.code.front(); if(t <= 0){ //如果时间不够执行这一条语句,退出当前程序。 wait.push_back(program); break; } if(s[2] == 'c'){ //如果是 lock 语句 if(isLock){ //如果当前是 lock 状态 stop.push(program); break; }else{ //否则进入锁定状态 isLock = true; } } //执行这条语句,并减少当前时间配额 t -= toTime[s[2]]; program.code.pop(); if(s[2] == 'l'){ isLock = false; if(!stop.empty()){ wait.push_front(stop.front()); stop.pop(); } } if(s[2] == '='){ char c; string t; int num; stringstream ss(s); ss >> c >> t >> num; ch[c-'a'] = num; } if(s[2] == 'i'){ cout << program.number << ": "<< ch[s[6]-'a'] << endl; } if(s[2] == 'd'){ break; } } } if(T) cout << endl; } return 0; }
例题 6-2 UVa 514
题目:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=455
思路:直接用栈,若有个车厢在不在栈顶并且所有的车厢都已经入栈了或出栈了,则是不可能的。
代码:
/* Rails (UVa 514) */ #include <iostream> #include <stack> #include <cstring> using namespace std; const int maxn = 1005; int main(){ //freopen("input.txt", "r", stdin); int n; while(cin >> n && n != 0){ int t; while(cin >> t && t != 0){ int a[maxn]; a[0] = t; for(int i=1; i<n; i++){ cin >> a[i]; } int cnt = 0; stack<int> stk; for(int i=0; i<n; i++){ while(1){ if(!stk.empty() && stk.top() == a[i]){ stk.pop(); break; }else{ stk.push(++cnt); if(cnt > n) //第 n+1 个车入栈了,不可能按照顺序输出了。 break; } } if(cnt > n) break; } if(cnt > n) cout << "No" << endl; else cout << "Yes" << endl; } cout << endl; } }
例题6-3 UVa 442
题目:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=383
思路: 用栈做,栈中元素是(行数,列数),用一个全局变量 cnt 统计乘法次数。遍历输入,若 s[i] == ')',则将栈顶的两个元素运算,并将运算后的(行数,列数)再压入栈,若 s[i] != '('(为字母),则将此矩阵压入栈。
代码:
/* Matrix Chain Multiplication (UVa 442) */ #include <iostream> #include <cstring> #include <stack> using namespace std; const int maxn = 30; int len[maxn][2]; //存放每个矩阵的行数和列数 int cnt; //计算次数 char s[1000]; //输入 struct RC{ int r, c; RC(int r, int c): r(r), c(c){} RC(){ r = 0; c = 0; } }; int main(){ //freopen("input.txt", "r", stdin); int n; cin >> n; getchar(); for(int i=0; i<n; i++){ char ch; cin >> ch; cin >> len[ch-'A'][0] >> len[ch - 'A'][1]; } while(cin >> s){ stack<RC> stk; cnt = 0; for(int i=0; i<strlen(s); i++){ if(s[i] == ')'){ //计算一次 RC a, b; b = stk.top(); stk.pop(); a = stk.top(); stk.pop(); if(a.c != b.r){ cnt = -1; break; }else{ cnt += a.r * a.c * b.c; stk.push(RC(a.r, b.c)); } }else if(s[i] != '('){ //如果是字母 stk.push(RC(len[s[i]-'A'][0], len[s[i]-'A'][1])); } } if(cnt == -1) cout << "error" << endl; else cout << cnt << endl; } return 0; }