2016级算法第二次上机-E.AlvinZH的儿时梦想——运动员篇
862-AlvinZH的儿时梦想——运动员篇
思路
难题。
应该想到,不管给出的数据如何,每一个淘汰的人不会对最终答案产生任何影响,所以每次淘汰就把人除掉就可以了,最后剩下的两个人计算它们从开始到相遇需要的时间就可以了。
首先对每个人根据初始位置进行排序,因为相遇总是先发生在相邻的两个人身上的,所以一开始先对相邻的人两两计算相遇时间,然后把相遇时间放进优先队列里(保证时间短的优先出队),然后依次出队,判定见面的两个人中哪个会被淘汰,然后把淘汰的人除去,维护新建立起来的相邻关系,以及新的相遇时间放进优先队列,一直处理直到队列只剩最后一对,然后取出来计算时间就可以了。
需要使用循环链表记录每一个人的相邻位置是谁,简单使用两个数组即可模拟循环链表。
本题还要注意的是环形跑道,也就是说在计算时间的时候记得相应处理,比如对跑道长度取模。注意看下列的求时间函数:
double getTime(int rear, int front)
{
int dx = (P[front].pos - P[rear].pos + L) % L;//相对距离
int dv = P[rear].v - P[front].v;//相对速度
if (dv < 0)//front追rear
{
dv = -dv;
dx = L - dx;
}
return (dx * 1.0 / dv);
}
分析
考察的是优先队列和循环链表。
最初状态环上有n个人,每次淘汰的必然是环上相邻的选手。注意到第一个被淘汰的人不会对后续过程有任何影响,所以找到这个人并把他从状态环上删去,就能把问题变成一个只有n-1人的子问题,此子问题与原问题有相同的答案。
利用优先队列维护状态环上所有相邻的人相遇的时间,每次取出最小值,可以淘汰一人,注意淘汰一人后,原本不相邻的人就相邻了,需要求得新的相遇时间入队,重复这一过程,直到队列剩余元素为1时结束。
考察了大家的模拟能力和手速,代码挺长,想起来还是挺简单的,对吧?
参考代码
//
// Created by AlvinZH on 2017/9/25.
// Copyright (c) AlvinZH. All rights reserved.
//
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <functional>
#include <algorithm>
#define MaxSize 100005
using namespace std;
struct Person {
int pos,v,power;
bool operator < (const Person& x) const {
return pos < x.pos;//按位置从小到大排序,pos小的优先级大(sort函数)
}
};
struct Race {
int front,rear;//两个人对应下标
double time;//相遇时间
Race(int r = 0,int f = 0,double t = 0.0) {
rear = r;front = f;time = t;
}
bool operator < (const Race& r) const {
return time > r.time;//相遇时间小的位于队首(优先队列)
}
};
int n,L;
Person P[MaxSize];
int nextP[MaxSize],lastP[MaxSize];//记录下一个和上一个人的标号
bool isOUT[MaxSize];//记录是否被淘汰
priority_queue<Race> Q;//优先队列
double getTime(int rear, int front)
{
int dx = (P[front].pos - P[rear].pos + L) % L;//相对距离
int dv = P[rear].v - P[front].v;//相对速度
if (dv < 0)//front追rear
{
dv = -dv;
dx = L - dx;
}
return (dx * 1.0 / dv);
}
int main()
{
//freopen("in1.txt", "r", stdin);
//freopen("out2.txt", "w", stdout);
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d %d", &n, &L);
for (int i = 0; i < n; i++) {
scanf("%d %d %d", &P[i].pos, &P[i].v, &P[i].power);
}
sort(P, P + n);
while (!Q.empty()) Q.pop();
for (int i = 0; i < n; i++) {
double t = getTime(i, (i + 1) % n);
Q.push(Race(i,(i+1)%n,t));
lastP[i] = (i - 1 + n) % n;
nextP[i] = (i + 1) % n;
}
int All = n;//剩余比赛人数
memset(isOUT, false, sizeof(isOUT));
while (Q.size() > 1)
{
Race tmp = Q.top();
Q.pop();
int rear = tmp.rear,front = tmp.front;
if(isOUT[rear] || isOUT[front])
continue;
if(lastP[rear] == front && nextP[front] == rear)//剩余最后两人
break;
if(P[rear].power > P[front].power)//rear追上front,淘汰front
{
isOUT[front] = true;
nextP[rear] = nextP[front];
lastP[nextP[front]] = rear;
double tt = getTime(rear, nextP[front]);
Q.push(Race(rear, nextP[rear], tt));
}
else
{
isOUT[rear] = true;
lastP[front] = lastP[rear];
nextP[lastP[rear]] = front;
double tt = getTime(lastP[front], front);
Q.push(Race(lastP[front], front, tt));
}
if(--All <= 0)
break;
}
Race tmp = Q.top();
Q.pop();
printf("%.3lf\n", tmp.time);
}
}
/*
* 考点:优先队列
* 坑:数据量较大
*/
2016级算法第二次上机-E.AlvinZH的儿时梦想——运动员篇的更多相关文章
- 2016级算法第二次上机-C.AlvinZH的儿时梦想——坦克篇
872 AlvinZH的儿时梦想----坦克篇 思路 简单题.仔细看题,题目意在找到直线穿过的矩形数最小,不能从两边穿过.那么我们只要知道每一行矩形之间的空隙位置就可以了. 如果这里用二维数组记住每一 ...
- 2016级算法第二次上机-A.画个圈圈诅咒你
890 画个圈圈诅咒你 思路 简单题.题目中的圆并没有什么实际作用,简化成线段重合问题会更好理解些. 暴力解法:使用双重for循环会T到想哭,记住最直接的方法一般是过不了题的. 解法一:二分查找.空间 ...
- 2016级算法第二次上机-G.ModricWang's Real QuickSort
873 思路 这是一道非常基础的题,目的是帮助大家回顾快排相关的知识.大家完成此题之后应该就对快排有比较深刻的印象了. 对于整个快排的流程,题目描述中已经给了清晰完整的伪代码.需要自己加工的部分就是, ...
- 2016级算法第二次上机-F.ModricWang's Number Theory II
891 ModricWang's Number Theory II 思路 使得序列的最大公约数不为1,就是大于等于2,就是找到一个大于等于2的数,它能够整除序列中的所有数. 考虑使得一个数d整除数组中 ...
- 2016级算法第二次上机-D.Bamboo的饼干
Bamboo的饼干 分析 从两个数组中各取一个数,使两者相加等于给定值.要注意去重和排序 难度不大,方法很多,基本只要不大于O(n^2 ) 的都可以过.本意想考察二分搜索 还可以借助stl中的map, ...
- 2016级算法第二次上机-B.Bamboo的OS实验
Bamboo的OS实验 分析 首先理解题意,要完成不同数量的不同命令,但是完成相同的命令之间必须有n个间隔,为使得时间最短,自然优先用其他命令来填充这n分钟的时间,由于数量少的命令可以用来填充空隙,所 ...
- 2016级算法第一次练习赛-F.AlvinZH的儿时梦想——机器人篇
864 AlvinZH的儿时梦想----机器人篇 题目链接:https://buaacoding.cn/problem/868/index 思路 中等题. 判断无限玩耍: \(p\) 的值能够承担的起 ...
- 2016级算法期末模拟练习赛-F.AlvinZH的青春记忆IV
1086 AlvinZH的青春记忆IV 思路 难题,动态规划. 这是一道很有意思的题,因为它不仅卡了时间,也卡了空间,而且卡的很妙很迷. 光是理解题意已经有点难度,简化题意:两串数字序列,相等的数字定 ...
- 2016级算法期末模拟练习赛-C.AlvinZH的青春记忆II
1084 AlvinZH的青春记忆II 思路 中等题,二分. 简化题意,一列数字,每秒会自动-1,特殊操作可以使一个数在1s内-k,问这些数都减至0需要多久. 答案肯定在[1,xMax]之间,采用二分 ...
随机推荐
- Canny效果
- git使用报错: fatal: Couldn't find remote ref master的解决方法
fatal: Couldn't find remote ref master 翻译过来就是:致命的:无法找到远程参考主,也就是报错的意思.错误的提示内容意思是找不到需要连接的对象. 解决方法有以下几种 ...
- 搭建Spring开发环境并编写第一个Spring小程序
搭建Spring开发环境并编写第一个Spring小程序 2015-05-27 0个评论 来源:茕夜 收藏 我要投稿 一.前面,我写了一篇Spring框架的基础知识文章,里面没 ...
- Oracle VM VirtualBox 部署CS devcloud2 开发环境
Setting up (VirtualBox) 1. Get the new DevCloud 2.0 virtual appliance. The new image was created usi ...
- Zedboard学习(三):PL下流水灯实验 标签: fpgazynqPL 2017-07-05 11:09 21人阅读 评论(0)
zynq系列FPGA分为PS部分和PL部分. PL: 可编程逻辑 (Progarmmable Logic), 就是FPGA部分. PS: 处理系统 (Processing System) , 就是与F ...
- RCC—使用 HSE/HIS 配置时钟
RCC :reset clock control 复位和时钟控制器:特别是要着重理解时钟树,理解了时钟树,F429 的一切时钟的来龙去脉都会了如指掌. STM32F4系列有5个时钟源: LSIRC( ...
- Perl 学习笔记-标量数据
最近学习Perl, 准备看一遍入门指南,关键的东西还是记录下来,以便以后复习和查看参考. 笔记来自<<Perl语言入门第5版>> 1. 在Perl内部,不区分整数值和浮点数值, ...
- springmvc框架简单搭建
一.利用xml 配置 1.web.xml <web-app version="2.4" xmlns="http://java.sun.com/xml/n ...
- Excel2016通过宏生成拼音码
一:视图---->宏---->录制宏 二:试图---->宏---->查看宏 三:点击编辑,输入如下代码片段,点击保存,并选择是 Function pinyin(p As Str ...
- [GO]使用map生成 json
package main import ( "encoding/json" "fmt" ) func main() { m := make(map[) //因为 ...