第六章 数据结构基础(例题篇)
例题6-1:并行程序模拟(Concurrency Simulator,UVa210) P139
双端队列:在中的双端队列deque
deque readyQ;
readyQ.push_front(1);//从队首插入元素
readyQ.push_back(2);//从队尾插入元素
int pid = readyQ.back();//取队尾元素
readyQ.pop_back();//弹出队尾元素
pid = readyQ.front();//取队首元素
readyQ.pop_front();//弹出队首元素
输入案例:
1
3 1 1 1 1 1 1
a = 4
print a
lock
b = 9
print b
unlock
print b
end
a = 3
print a
lock
b = 8
print b
unlock
print b
end
b = 5
a = 17
print a
print b
lock
b = 21
print b
unlock
print b
end
#include<cstdio>
#include<queue>
#include<cstring>
#include<cctype>
using namespace std;
const int maxn = 1000;
deque<int> readyQ;
queue<int> blockQ;
int n, quantum, c[5], var[26], ip[maxn];/*ip[pid]是程序pid的当前行号。
所有程序都存在prog数组,更类似真实的情况,代码也更短。*/
bool locked;
char prog[maxn][10];
void run(int pid)
{
int q = quantum;
while (q > 0)
{
char *p = prog[ip[pid]];
switch (p[2])
{
case '=':
var[p[0] - 'a'] = isdigit(p[5]) ? (p[4] - '0') * 10 + p[5] - '0' : p[4] - '0';
q -= c[0];
break;
case 'i'://print
printf("%d: %d\n", pid + 1, var[p[6] - 'a']);
q -= c[1];
break;
case 'c'://lock
if (locked)
{
blockQ.push(pid);
return;
}
locked = true;
q -= c[2];
break;
case 'l'://unlock
locked = false;
if (!blockQ.empty())
{
int pid2 = blockQ.front();
blockQ.pop();
readyQ.push_front(pid2);
}
q -= c[3];
break;
case 'd'://end
return;
}
ip[pid]++;
}
readyQ.push_back(pid);
}
int main()
{
freopen("input.txt", "rb", stdin);
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d %d %d %d %d %d %d\n", &n, &c[0], &c[1], &c[2], &c[3], &c[4], &quantum);
memset(var, 0, sizeof(var));
int line = 0;
for (int i = 0;i < n;i++)
{
fgets(prog[line++], maxn, stdin);
ip[i] = line - 1;
while (prog[line - 1][2] != 'd')
fgets(prog[line++], maxn, stdin);
readyQ.push_back(i);
}
locked = false;
while (!readyQ.empty())
{
int pid = readyQ.front();
readyQ.pop_front();
run(pid);
}
if (T)
printf("\n");
}
return 0;
}
例题6-2:铁轨(Rails,UVa514) P140
输入案例:
5
1 2 3 4 5
5 4 1 2 3
0
6
6 5 4 3 2 1
0
0
输出答案:
YES
NO
YES
#include<cstdio>
#include<stack>
using namespace std;
const int MAXN = 1000 + 10;
int n, target[MAXN];
int main()
{
freopen("input.txt", "rb", stdin);
while (scanf("%d", &n) == 1)
{
while (scanf("%d", &target[1]) == 1 && target[1] != 0)
{
stack<int> s;
int A = 1, B = 1;
for (int i = 2;i <= n;i++)
{
scanf("%d", &target[i]);
}
int ok = 1;
while (B <= n)
{
if (A == target[B])
{
A++;
B++;
}
else if (!s.empty() && s.top() == target[B])
{
s.pop();
B++;
}
else if (A <= n)
s.push(A++);
else
{
ok = 0;
break;
}
}
printf("%s\n", ok ? "Yes" : "No");
}
printf("\n");
}
return 0;
}
例题6-4:破损的键盘(又名:悲剧文本)(Broken Keyboard,UVa11988) P143
循环链表
链表(linked list)
输入案例:
This_is_a_[Beiju]_text
[[]][][]Happy_Birthday_to_Tsinghua_University
输出答案:
BeijuThis_is_a__text
Happy_Birthday_to_Tsinghua_University
#include<iostream>
#include<string>
#include<stack>
using namespace std;
const int maxn = 100000 + 5;
int last, cur, nextlist[maxn];//光标位于cur号字符之后面
char s[maxn];
int main()
{
freopen("input.txt", "rb", stdin);
freopen("output.txt", "wb", stdout);
while (scanf("%s", s + 1) == 1)
{
int n = strlen(s + 1);//输入保存在s[1],s[2]...中
last = cur = 0;
nextlist[0] = 0;
for (int i = 1;i <= n;i++)
{
char ch = s[i];
if (ch == '[')
cur = 0;
else if (ch == ']')
cur = last;
else
{
nextlist[i] = nextlist[cur];
nextlist[cur] = i;
if (cur == last)
last = i;//更新“最后一个字符”编号
cur = i;//移动光标
}
}
for (int i = nextlist[0];i != 0;i = nextlist[i])
printf("%c", s[i]);
printf("\r\n");
}
return 0;
}
例题6-5:移动盒子(Boxes in a Line,UVa12657) P144
循环双向链表
双向链表(double linked list)
输入案例:
6 4
1 1 4
2 3 5
3 1 6
4
6 3
1 1 4
2 3 5
3 1 6
100000 1
4
输出答案:
Case 1: 12
Case 2: 9
Case 3: 2500050000
#include<iostream>
using namespace std;
const int maxn = 100000 + 5;
int n, leftlist[maxn], rightlist[maxn];
inline void link(int L, int R)
{
rightlist[L] = R;
leftlist[R] = L;
}
int main()
{
freopen("input.txt", "rb", stdin);
freopen("output.txt", "wb", stdout);
int m, kase = 0;
while (scanf("%d%d", &n, &m) == 2)
{
for (int i = 1;i <= n;i++)
{
leftlist[i] = i - 1;
rightlist[i] = (i + 1) % (n + 1);
}
rightlist[0] = 1;
leftlist[0] = n;
int op, X, Y, inv = 0;
while (m--)
{
scanf("%d", &op);
if (op == 4)
inv = !inv;
else
{
scanf("%d%d", &X, &Y);
if (op == 3 && rightlist[Y] == X)swap(X, Y);
if (op != 3 && inv)op = 3 - op;
if (op == 1 && X == leftlist[Y])continue;
if (op == 2 && X == rightlist[Y])continue;
int LX = leftlist[X], RX = rightlist[X], LY = leftlist[Y], RY = rightlist[Y];
if (op == 1)
{
link(LX, RX);link(LY, X);link(X, Y);
}
else if (op == 2)
{
link(LX, RX);link(Y, X);link(X, RY);
}
else if (op == 3)
{
if (rightlist[X] == Y)
{
link(LX, Y);link(Y, X);link(X, RY);
}
else
{
link(LX, Y);link(Y, RX);link(LY, X);link(X, RY);
}
}
}
}
int b = 0;
long long ans = 0;
for (int i = 1;i <= n;i++)
{
b = rightlist[b];
if (i % 2 == 1)
ans += b;
}
if (inv&&n % 2 == 0)
ans = (long long)n*(n + 1) / 2 - ans;
printf("Case %d: %lld\r\n",++kase,ans);
}
return 0;
}