热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

《算法竞赛入门经典》第六章数据结构基础题解(一)

深入探讨栈和队列的应用实例——铁轨问题(Rails,ACM/ICPCCERC1997,UVa514)。该问题设定在一个城市火车站,涉及n节车厢从A方向驶入车站,并需按照特定顺序驶出B方向的铁轨。本文将通过算法实现来验证特定顺序的可行性。
### 探讨栈与队列的应用
#### 铁轨问题(Rails, ACM/ICPC CERC 1997, UVa 514)
**问题背景**
假设某城市火车站有n节车厢从A方向驶入,这些车厢按照1至n的顺序编号。任务是确定这些车厢是否能以特定的顺序从B方向的铁轨驶出。例如,顺序(5,4,3,2,1)是可行的,而(5,4,1,2,3)则不可行。

```cpp
#include
#include
using namespace std;
const int MAXN = 1010;
int n, target[MAXN];
int main() {
while (scanf("%d", &n) == 1) {
stack s;
int A = 1, B = 1;
for (int i = 1; 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]) {
B++;
s.pop();
} else if (A <= n) {
s.push(A);
A++;
} else {
ok = 0;
break;
}
}
printf("%s\n", ok ? "Yes" : "No");
}
return 0;
}
```

#### 矩阵链乘问题(Matrix Chain Multiplication, UVa 442)
**问题背景**
给定n个矩阵的维度和一些矩阵链乘表达式,计算乘法所需的总次数。如果乘法无法进行,则输出错误信息。例如,三个矩阵A(50x10),B(10x20),C(20x5),则(A(BC))的乘法次数为10*20*5 + 50*10*5 = 3500。

```cpp
#include
#include
#include
#include
using namespace std;
struct Matrix {
int a, b;
Matrix(int a = 0, int b = 0):a(a), b(b) {}
} m[26];
stack s;
int main() {
int n;
cin >> n;
for (int i = 0; i string name;
cin >> name;
int k = name[0] - 'A';
cin >> m[k].a >> m[k].b;
}
string expr;
while (cin >> expr) {
int len = expr.length();
bool error = false;
int ans = 0;
for (int i = 0; i if (isalpha(expr[i]))
s.push(m[expr[i]-'A']);
else if (expr[i] == ')') {
Matrix m2 = s.top();
s.pop();
Matrix m1 = s.top();
s.pop();
if (m1.b != m2.a) {
error = true;
break;
}
ans += m1.a * m1.b * m2.b;
s.push(Matrix(m1.a, m2.b));
}
}
if (error)
printf("error\n");
else
printf("%d\n", ans);
}
return 0;
}
```

### 链表的应用
#### 破损的键盘问题(Broken Keyboard, UVa 11988)
**问题背景**
输入包含多组数据,每组数据由不超过100000个字母、下划线、字符“[”或“]”组成。其中“[”表示Home键,“]”表示End键。任务是模拟键盘操作,输出最终显示在屏幕上的文本。

```cpp
#include
#include
using namespace std;
const int maxn = 100005;
int last, cur, next[maxn];
char s[maxn];
int main() {
while (scanf("%s", s+1) == 1) {
int n = strlen(s+1);
last = cur = 0;
next[0] = 0;
for (int i = 1; i <= n; i++) {
if (s[i] == '[') {
cur = 0;
} else if (s[i] == ']') {
cur = last;
} else {
next[i] = next[cur];
next[cur] = i;
if (cur == last) {
last = i;
}
cur = i;
}
}
for (int i = next[0]; i != 0; i = next[i]) {
printf("%c", s[i]);
}
printf("\n");
}
return 0;
}
```

#### 盒子移动问题(Boxes in a Line, UVa 12657)
**问题背景**
有一行编号为1至n的盒子,支持四种操作:将盒子X移至Y左侧、将盒子X移至Y右侧、交换X和Y的位置、反转整个序列。任务是在一系列操作后,计算所有奇数位置盒子编号的总和。

```cpp
#include
#include
#include
using namespace std;
const int MAXN = 100050;
int n;
int right[MAXN], left[MAXN];
void Link(int L, int R) {
right[L] = R;
left[R] = L;
}
int main() {
int m, kase = 0;
while (scanf("%d%d", &n, &m) == 2) {
for (int i = 1; i <= n; i++) {
left[i] = i-1;
right[i] = (i+1) % (n+1);
}
right[0] = 1;
left[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 && right[Y] == X)
swap(X, Y);
if (op != 3 && inv)
op = 3 - op;
if (op == 1 && X == left[Y])
continue;
if (op == 2 && X == right[Y])
continue;

int LX = left[X], RX = right[X], LY = left[Y], RY = right[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 (right[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 = right[b];
if (i%2)
ans += b;
}
if (inv && n%2 == 0)
ans = (long long)n*(n+1) / 2 - ans;
printf("Case %d: %lld\n", ++kase, ans);
}
return 0;
}
```

推荐阅读
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 在金融和会计领域,准确无误地填写票据和结算凭证至关重要。这些文件不仅是支付结算和现金收付的重要依据,还直接关系到交易的安全性和准确性。本文介绍了一种使用C语言实现小写金额转换为大写金额的方法,确保数据的标准化和规范化。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • Codeforces Round #566 (Div. 2) A~F个人题解
    Dashboard-CodeforcesRound#566(Div.2)-CodeforcesA.FillingShapes题意:给你一个的表格,你 ... [详细]
  • 本题探讨如何通过最大流算法解决农场排水系统的设计问题。题目要求计算从水源点到汇合点的最大水流速率,使用经典的EK(Edmonds-Karp)和Dinic算法进行求解。 ... [详细]
  • 作者:守望者1028链接:https:www.nowcoder.comdiscuss55353来源:牛客网面试高频题:校招过程中参考过牛客诸位大佬的面经,但是具体哪一块是参考谁的我 ... [详细]
  • 本题旨在通过给定的评级信息,利用拓扑排序和并查集算法来确定全球 Tetris 高手排行榜。题目要求判断是否可以根据提供的信息生成一个明确的排名表,或者是否存在冲突或信息不足的情况。 ... [详细]
  • 本题探讨了在一个有向图中,如何根据特定规则将城市划分为若干个区域,使得每个区域内的城市之间能够相互到达,并且划分的区域数量最少。题目提供了时间限制和内存限制,要求在给定的城市和道路信息下,计算出最少需要划分的区域数量。 ... [详细]
  • 深入解析Redis内存对象模型
    本文详细介绍了Redis内存对象模型的关键知识点,包括内存统计、内存分配、数据存储细节及优化策略。通过实际案例和专业分析,帮助读者全面理解Redis内存管理机制。 ... [详细]
  • 本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • 本题涉及一棵由N个节点组成的树(共有N-1条边),初始时所有节点均为白色。题目要求处理两种操作:一是改变某个节点的颜色(从白变黑或从黑变白);二是查询从根节点到指定节点路径上的第一个黑色节点,若无则输出-1。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • 深入探讨CPU虚拟化与KVM内存管理
    本文详细介绍了现代服务器架构中的CPU虚拟化技术,包括SMP、NUMA和MPP三种多处理器结构,并深入探讨了KVM的内存虚拟化机制。通过对比不同架构的特点和应用场景,帮助读者理解如何选择最适合的架构以优化性能。 ... [详细]
author-avatar
Theduck_king
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有