学习记录
队列
通常是要定义一个头指针,一个尾指针,在操作的时候分别对其进行操作,(虽然会占用空间较多,但是时间会比较节约)当head头指针与tail尾指针相遇的时候代表队列为空,结束。
队列遵循“先进先出”的原则(First In First Out)
通常可以把队列的三个基本元素(一个数组,两个变量(头指针尾指针))放在结构体内,就可以简单对队列进行操作。
typedef struct quene {
int data[100];
int head;
int tail;
}Qe;
//队列初学习
typedef struct quene {
int data[100];
int head;
int tail;
}Qe;
int main()
{
Qe q;
q.head = 1;
q.tail = 1;
for (int i = 0; i < 9; i++)
{
scanf("%d", &q.data[q.tail]);
q.tail++;
}
while (q.head < q.tail)
{
printf("%d ", q.data[q.head]);
q.head++;
q.data[q.tail] = q.data[q.head];
q.tail++;
q.head++;
}
return 0;
}
栈
栈不同于队列的先进先出,而是后进先出。(可以想象成一个筐子,先放进去的沉在最底下,后放进去的在最上面)
栈的初认识
int main()
{
char a[100] = { 0 }, s[100] = { 0 };
gets(a);
int len = strlen(a);
int mid = len / 2 - 1;
int top = 0;
for (int i = 0; i <= mid; i++)
{
s[++top] = a[i];
}
int next = 0;
if (len % 2 == 0)
next = mid + 1;
else
next = mid + 2;
for (int i = next; i < len ; i++)
{
if (s[top] != a[i])
break;
top--;
}
if (top == 0)
printf("YES");
else
printf("NO");
return 0;
}
啊哈算法----小猫钓鱼
typedef struct quene //两个人手上的牌
{
int data[1000];
int head;
int tail;
}Qun;
typedef struct stack //桌面上的牌最多就只有10张 因为牌面是0-9
{
int data[100];
int top;
}Stk;
int main()
{
Qun q1, q2;
Stk s;
int book[10] = { 0 };
q1.head = 1;
q1.tail = 1;
q2.head = 1;
q2.tail = 1;
s.top = 0;
int t = 0;
for (int i = 0; i < 6; i++)
{
scanf("%d", &q1.data[q1.tail]);
q1.tail++;
}
for (int i = 0; i < 6; i++)
{
scanf("%d", &q2.data[q2.tail]);
q2.tail++;
}
while (q1.head < q1.tail && q2.head < q2.tail)
{
t = q1.data[q1.head];
if (book[t] == 0) //1没有赢牌
{
q1.head++;
s.top++;
s.data[s.top] = t;
book[t] = 1;
}
else //1赢牌了,需要拿牌
{
q1.head++;
q1.data[q1.tail] = t;
q1.tail++;
while (s.data[s.top] != t)
{
book[s.data[s.top]] = 0;
q1.data[q1.tail] = s.data[s.top];
q1.tail++;
s.top--;
}
book[s.data[s.top]] = 0;
q1.data[q1.tail] = s.data[s.top];
q1.tail++;
s.top--;
}
if (q1.head == q1.tail)
break;
t = q2.data[q2.head];
if (book[t] == 0) //2没有赢牌
{
q2.head++;
s.top++;
s.data[s.top] = t;
book[t] = 1;
}
else //2赢牌了,需要拿牌
{
q2.head++;
q2.data[q2.tail] = t;
q2.tail++;
while (s.data[s.top] != t)
{
book[s.data[s.top]] = 0;
q2.data[q2.tail] = s.data[s.top];
q2.tail++;
s.top--;
}
book[s.data[s.top]] = 0;
q2.data[q2.tail] = s.data[s.top];
q2.tail++;
s.top--;
}
}
if (q2.head == q2.tail)
{
printf("1 win\n");
printf("1当前手上的牌为:");
for (int i = q1.head; i <= q1.tail - 1; i++)
{
printf("%d ", q1.data[i]);
}
if (s.top > 0)
{
printf("\n桌上的牌是:");
for (int i = 1; i <= s.top; i++)
{
printf("%d ", s.data[i]);
}
}
else
printf("\n桌上没有牌了");
}
else
{
printf("2 win\n");
printf("2当前手上的牌为:");
for (int i = q2.head; i <= q2.tail - 1; i++)
{
printf("%d ", q2.data[i]);
}
if (s.top > 0)
{
printf("\n桌上的牌是:");
for (int i = 1; i <= s.top; i++)
{
printf("%d ", s.data[i]);
}
}
else
printf("\n桌上没有牌了");
}
return 0;
}
测试题
P1055 [NOIP2008 普及组] ISBN 号码
# [NOIP2008 普及组] ISBN 号码
## 题目描述
每一本正式出版的图书都有一个 ISBN 号码与之对应,ISBN 码包括 $9$ 位数字、$1$ 位识别码和 $3$ 位分隔符,其规定格式如 `x-xxx-xxxxx-x`,其中符号 `-` 就是分隔符(键盘上的减号),最后一位是识别码,例如 `0-670-82162-4`就是一个标准的 ISBN 码。ISBN 码的首位数字表示书籍的出版语言,例如 $0$ 代表英语;第一个分隔符 `-` 之后的三位数字代表出版社,例如 $670$ 代表维京出版社;第二个分隔符后的五位数字代表该书在该出版社的编号;最后一位为识别码。
识别码的计算方法如下:
首位数字乘以 $1$ 加上次位数字乘以 $2$ ……以此类推,用所得的结果 $ \bmod 11$,所得的余数即为识别码,如果余数为 $10$,则识别码为大写字母 $X$。例如 ISBN 号码 `0-670-82162-4` 中的识别码 $4$ 是这样得到的:对 `067082162` 这 $9$ 个数字,从左至右,分别乘以 $1,2,\dots,9$ 再求和,即 $0\times 1+6\times 2+……+2\times 9=158$,然后取 $158 \bmod 11$ 的结果 $4$ 作为识别码。
你的任务是编写程序判断输入的 ISBN 号码中识别码是否正确,如果正确,则仅输出 `Right`;如果错误,则输出你认为是正确的 ISBN 号码。
## 输入格式
一个字符序列,表示一本书的 ISBN 号码(保证输入符合 ISBN 号码的格式要求)。
## 输出格式
一行,假如输入的 ISBN 号码的识别码正确,那么输出 `Right`,否则,按照规定的格式,输出正确的 ISBN 号码(包括分隔符 `-`)。
## 样例 #1
### 样例输入 #1
```
0-670-82162-4
```
### 样例输出 #1
```
Right
```
## 样例 #2
### 样例输入 #2
```
0-670-82162-0
```
### 样例输出 #2
```
0-670-82162-4
```
## 提示
2008 普及组第一题
P1055 [NOIP2008 普及组] ISBN 号码
int main()
{
char str[20];
gets(str);
int len = strlen(str);
int a[11];
int t = 1;
int sum = 0;
for (int i = 0; i < len; i++)
{
if (str[i] >= '0' && str[i] <= '9')
{
a[t] = str[i] - '0';
t++;
}
}
for (int i = 1; i <= 9; i++)
{
sum += a[i] * i;
}
int b = sum % 11;
if (b == a[10])
{
printf("Right");
}
else
{
str[len - 1] = (b + '0');
printf("%s", str);
}
return 0;
}
P9064 [yLOI2023] 苦竹林
# [yLOI2023] 苦竹林
## 题目背景
> 悬挂在屋檐下的风铃,摇晃的声音很动听。
> 思念就像梅雨下不停,我的心境一片泥泞。
> 散落在天际里的繁星,闪烁着你我的宿命。
> 当枫叶轻盈落入湖心,近看山水一片宁静。
——银临 & 涵昱《苦竹林》
## 题目描述
共有 $n$ 个风铃悬挂在屋檐下,每个风铃都能发出一定音调的声音。从左到右给风铃从 $1$ 至 $n$ 编号,第 $i$ 个风铃的音调是 $a_i$。
为了表达内心的思念,扶苏决定在 $n$ 个的风铃中取出 $m$ 个,送给远方的朋友。
请你找到最小的整数 $\varepsilon$,使得存在一种方案,能够从 $n$ 个风铃中挑出 $m$ 个,设挑出风铃的音调为 $b_1, b_2, \dots b_m$,满足对任意的 $1 \leq i, j \leq m$,都有 $|b_i - b_j| \leq \varepsilon$。
## 输入格式
第一行是两个整数,表示风铃的个数 $n$ 和挑选出风铃的个数 $m$。
第二行有 $n$ 个整数,表示每个风铃的音调。第 $i$ 个整数表示 $a_i$。
## 输出格式
输出一行一个整数,表示最小的 $\varepsilon$。
## 样例 #1
### 样例输入 #1
```
5 3
1 2 3 4 5
```
### 样例输出 #1
```
2
```
## 样例 #2
### 样例输入 #2
```
6 4
1 7 8 3 4 6
```
### 样例输出 #2
```
4
```
## 提示
### 样例 2 解释
一种选择的方案是选择第 $2,4,5,6$ 四个风铃,音调依次为 $7,3,4,6$。可以得到对任何的 $1 \leq i, j\leq 4$,都有 $|b_i - b_j| \leq 4$。
另一种方案是选择第 $2,3,5,6$ 四个风铃,同样计算得到的 $\varepsilon$ 为 $4$。
### 数据规模与约定
- 对 $10\%$ 的数据,$m = 2$。
- 另有 $10\%$ 的数据,$m = n$。
- 对 $40\%$ 的数据,$n \leq 5$。
- 对 $60\%$ 的数据,保证对所有的 $2 \leq i \leq n$,满足 $a_{i - 1} \leq a_i$,即 $a_i$ 单调不降。
- 对 $80\%$ 的数据,$n \leq 10^3$。
- 对 $100\%$ 的数据,$2 \leq m \leq n \leq 10^5$,$1 \leq a_i \leq 10^9$。
### 说明
本题共有三个附加样例文件,见题目附件中的 `ring.zip`。
P9064 [yLOI2023] 苦竹林
int main()
{
int n = 0, m = 0; //风铃数n 取m
int a[100001];
scanf("%d%d", &n, &m);
int num = 0;
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n-1-i; j++)
{
if (a[j] > a[j + 1])
{
int t = a[j];
a[j] = a[j + 1];
a[j + 1] = t;
}
}
}
if (n % 2 != 0)
{
int mid = (n - 1) / 2;
if (m % 2 != 0)
{
int t = (m - 1) / 2;
num = a[mid + t] - a[mid - t];
printf("%d", num);
}
else
{
int t = m / 2;
int num1 = 0, num2 = 0;
num1 = a[mid + t] - a[mid + 1 - t];
num2 = a[mid - 1 + t] - a[mid - t];
if (num1 > num2)
num = num1;
else
num = num2;
printf("%d", num);
}
}
else if (n % 2 == 0)
{
int mid1 = n / 2 - 1;
int mid2 = n / 2;
if (m % 2 == 0)
{
int t = (m - 2) / 2;
num = a[mid2 + t] - a[mid1 - t];
printf("%d", num);
}
else
{
int t = (m - 2 + 1) / 2;
int num1 = a[mid2 - 1 + t] - a[mid1 - t];
int num2 = a[mid2 + t] - a[mid1 + 1 - t];
if (num1 > num2)
num = num1;
else
num = num2;
printf("%d", num);
}
}
return 0;
}
P2032 扫描
# 扫描
## 题目描述
有一个 $1 \times n$ 的矩阵,有 $n$ 个整数。
现在给你一个可以盖住连续 $k$ 个数的木板。
一开始木板盖住了矩阵的第 $1 \sim k$ 个数,每次将木板向右移动一个单位,直到右端与第 $n$ 个数重合。
每次移动前输出被覆盖住的数字中最大的数是多少。
## 输入格式
第一行两个整数 $n,k$,表示共有 $n$ 个数,木板可以盖住 $k$ 个数。
第二行 $n$ 个整数,表示矩阵中的元素。
## 输出格式
共 $n - k + 1$ 行,每行一个整数。
第 $i$ 行表示第 $i \sim i + k - 1$ 个数中最大值是多少。
## 样例 #1
### 样例输入 #1
```
5 3
1 5 3 4 2
```
### 样例输出 #1
```
5
5
4
```
## 提示
对于 $20\%$ 的数据,$1 \leq k \leq n \leq 10^3$。
对于 $50\%$ 的数据,$1 \leq k \leq n \leq 10^4$。
对于 $100\%$ 的数据,$1 \leq k \leq n \leq 2 \times 10^6$,矩阵中的元素大小不超过 $10^4$ 并且均为正整数。
//P2032 扫描
int main()
{
int n = 0, k = 0, max = 0;
scanf("%d%d", &n, &k);
int a[100] = { 0 };
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
for (int i = 0; i < n - k + 1; i++)
{
max = a[i];
for (int j = i; j < i + k; j++)
{
if (max < a[j])
max = a[j];
}
printf("%d\n", max);
}
return 0;
}
P4387 【深基15.习9】验证栈序列
# 【深基15.习9】验证栈序列
## 题目描述
给出两个序列 pushed 和 poped 两个序列,其取值从 1 到 $n(n\le100000)$。已知入栈序列是 pushed,如果出栈序列有可能是 poped,则输出 `Yes`,否则输出 `No`。为了防止骗分,每个测试点有多组数据。
## 输入格式
第一行一个整数 $q$,询问次数。
接下来 $q$ 个询问,对于每个询问:
第一行一个整数 $n$ 表示序列长度;
第二行 $n$ 个整数表示入栈序列;
第三行 $n$ 个整数表示出栈序列;
## 输出格式
对于每个询问输出答案。
## 样例 #1
### 样例输入 #1
```
2
5
1 2 3 4 5
5 4 3 2 1
4
1 2 3 4
2 4 1 3
```
### 样例输出 #1
```
Yes
No
```
int main()
{
int q = 0;
scanf("%d", &q);
for (int k = 0; k < q; k++)
{
int n = 0, t = 0;
scanf("%d", &n);
int a[1000] = { 0 }, b[1000] = { 0 };
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
t++;
}
for (int i = 0; i < n; i++)
{
scanf("%d", &b[i]);
}
int key = 0;
for (int i = 0; i < n; i++)
{
t--;
if (a[t] != b[i])
{
key = 1;
break;
}
}
if (key == 0)
printf("YES\n");
else if(key==1)
printf("NO\n");
}
return 0;
}