mirror of
https://github.com/xlucn/PAT.git
synced 2026-02-08 03:51:36 +08:00
update markdown file a1012-a1014
This commit is contained in:
16
md/a1012.md
16
md/a1012.md
@@ -51,16 +51,20 @@
|
||||
|
||||
我的方法是在读取学生成绩的时候顺便记录0~100分各有多少人,然后根据得分人数计算排名。举个例子:
|
||||
|
||||
- 如果100分有1人,99分有2人,98分有3人,97分有4人。那么得100分的排名是1,得99分的排名是2(并列),98分的排名是4(并列),97分的排名是7(并列)。
|
||||
- 如果100分有1人,99分有2人,98分有3人,97分有4人。
|
||||
|
||||
规律是什么?如果分数从高到低是a1,a2,a3,...ai,...,那么
|
||||
那么
|
||||
|
||||
- a[i]的名次 = a[i-1]的名次 + a[i-1]的人数
|
||||
- a[1]的名次 = 1
|
||||
- 得100分的排名是1,得99分的排名是2(并列),98分的排名是4(并列),97分的排名是7(并列)。
|
||||
|
||||
这其实是递归定义,如果定义一个不存在的高分a[0]人数=1(比如101分)(代码中一开始的初始化就是做这个),那么
|
||||
规律是什么?如果学生获得的分数分别有a1>a2>a3>...>ai>...,那么
|
||||
|
||||
- **a[i]的名次 = a[0]~a[i-1]的人数总和**,(i>0)
|
||||
- 分数a[i]的名次 = 分数a[i-1]的名次 + 分数a[i-1]的人数
|
||||
- 分数a[1]的名次 = 1
|
||||
|
||||
这其实是递归定义,如果定义一个不存在的高分a0(比如101分)人数=1(代码中一开始的初始化就是做这个),那么上面的关系就简化成了
|
||||
|
||||
- **分数a[i]的名次 = a[0]~a[i-1]的人数总和**,(i>0)
|
||||
|
||||
可以验证一下:97分的排名=98~101分人数总和=3+2+1+1=7
|
||||
|
||||
|
||||
@@ -171,4 +171,4 @@ int main()
|
||||
//}
|
||||
//}
|
||||
|
||||
```
|
||||
```
|
||||
76
md/a1014.md
76
md/a1014.md
@@ -36,6 +36,80 @@
|
||||
## 思路
|
||||
|
||||
|
||||
### 题意解读:
|
||||
|
||||
银行有N个窗口, 每个窗口允许排M个顾客. 一大早8点所有顾客商量好蜂拥而入,
|
||||
那么情况有两种: 1, 顾客全部能排在队伍里; 2, 顾客人数太多, 有人排在外面,
|
||||
要等前面的顾客完成离开, 再进入列列.
|
||||
|
||||
**注意点**:
|
||||
|
||||
- 时间截止的标准是: 进入列列不晚于下午5点即可. 也就是说以进入列列时间为标准,
|
||||
中间用多长时间都没问题. 这个点包括我很多人肯定第一感觉是理解错的.
|
||||
|
||||
### 代码结构
|
||||
|
||||
解读题目时提到可以存在两种情况, 我将这两种情况合并了一下:
|
||||
|
||||
- 顾客一共有K个, 如果`K<=M*N`, 那么我用下面这图表示人次的流动情况(E表示入列, D表示
|
||||
出列, -表示此时无此操作):
|
||||
|
||||
```
|
||||
时间顺序或者操作顺序-->
|
||||
出列: -----------------DDD...(K*D)...DDD
|
||||
入列: EEE...(K*E)...EEE-----------------
|
||||
```
|
||||
|
||||
即表示一起进行K次入列, 然后一起进行K次出列, 就完成了.
|
||||
|
||||
- 如果`K>M*N`, 那么其中有一段时间会交替有人出列/入列, 表示起来就是:
|
||||
|
||||
```
|
||||
时间顺序或者操作顺序-->
|
||||
出列: ----(M*N)-----DDDDDD...(K*D)...DDD
|
||||
入列: EEE...(K*E)...EEEEEE----(M*N)-----
|
||||
```
|
||||
|
||||
这表示前M*N次只有入列, 中间有顾客出列, 有顾客入列, 最后M*N次只有出列.
|
||||
|
||||
总结这两种情况, 都是前K次是入列, 后K次是出列, 只需再计算出总的操作次数(出入记为
|
||||
一次)即可, 其实就是`max(2*K, M*N+K)`.
|
||||
|
||||
这样代码结构就是
|
||||
|
||||
```
|
||||
循环max(2*K, M*N+K)次:
|
||||
如果是后K次:
|
||||
出列
|
||||
如果是前K次:
|
||||
入列
|
||||
```
|
||||
|
||||
### 计时方法
|
||||
|
||||
数据结构:
|
||||
|
||||
- 用一个数组(长度至少为K+1, 后面解释)先记录每个顾客的所需时间. 后面操作将这个时间
|
||||
更新为顾客入列时间.
|
||||
|
||||
时间为距离早8点的分钟数.
|
||||
|
||||
如实按顾客编号(即从1开始)记录, 角标为0的元素保持为0.
|
||||
|
||||
- 用N个队列模拟相关过程, 记录内容为顾客标号, 但是队列长度至少为M+1(后面解释)
|
||||
|
||||
操作主要在入列时(因为入列时间很重要)
|
||||
|
||||
入列时:
|
||||
|
||||
- 找到长度最短的队列
|
||||
- 找到前面一个人的(包括标号0)对应时间
|
||||
- 将将要入列的人的时间加上上述时间, 即得到了此人的入列时间
|
||||
|
||||
出列时:
|
||||
|
||||
- 只需找到所有队列队首中时间最早的对其出列即可
|
||||
|
||||
## 代码
|
||||
|
||||
[最新代码@github](https://github.com/OliverLew/PAT/blob/master/PATAdvanced/1014.c),欢迎交流
|
||||
@@ -110,4 +184,4 @@ int main()
|
||||
return 0;
|
||||
}
|
||||
|
||||
```
|
||||
```
|
||||
Reference in New Issue
Block a user