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]之间,采用二分 ...
随机推荐
- MAXOS 进程管理
ps -ef|grep +程序名 注意进程名区分大小写 linux上进程有5种状态:1. 运行(正在运行或在运行队列中等待)2. 中断(休眠中, 受阻, 在等待某个条件的形成或接受到信号)3. 不可中 ...
- zabbix自定义key监控nginx和fpm(网站并发数)
一. nginx编译参数 监控nginx,主要讲解监控并发数 --prefix=/usr/local/nginx --with-http_stub_status_module zabbix编译参数的查 ...
- Android TV上的焦点切换效果
转载:http://blog.csdn.net/wzlas111/article/details/39741091 Android TV上的焦点凸显特效相信大家都看到过,那么我们就来实现它吧,首先上张 ...
- Python简单邮件发送源码
环境: Python27 主要代码: # -*- coding: utf-8 -*- ''' Created on 2016年10月18日 @author: xuxianglin ''' import ...
- Openssl enc命令
一.简介 enc - 对称加密例程,使用对称密钥对数据进行加解密,特点是速度快,能对大量数据进行处理.算法有流算法和分组加密算法,流算法是逐字节加,由于其容易被破译,现在已很少使用:分组加密算法是将数 ...
- 冲刺NOIP2015提高组复赛模拟试题(五)1.数学作业
1. 数学作业 [问题描述] 路人丙的数学老师非常乏力,他喜欢出一些非常乏力的数学题来为难乏力的学生们.这次数学老师布置了一堆的数学题作为作业,而且这些数学题有个共同的特点是都求C(N,M)中不同质因 ...
- [SoapUI] 获取Cookie,并循环遍历当前Project下所有的Test Suite,Test Case,Test Step,将Cookie传递给这些Test Step
import com.eviware.soapui.support.types.StringToStringMap //Get all th cookies in the response , her ...
- C# 集合的使用List<T>的使用
C# List<T>用法 所属命名空间:using System.Collections.Generic; List<T>类是 ArrayList 类的泛型等效类. 该类使用 ...
- javascript总结21:javascript-JSON与遍历
1 什么是JSON JavaScript Object Notation(JavaScript对象表示形式) JavaScript的子集 JSON和对象字面量的区别 JSON的属性必须用双引号引号引起 ...
- 8) Struts2 2 SpringMVC
git@github.com:witaste/smse.git 数据库脚本: /* Navicat MySQL Data Transfer Source Server : 新服务器 Source Se ...