2016 ICPC Mid-Central USA Region J. Windy Path (贪心)
比赛链接:2016 ICPC Mid-Central USA Region
题目链接:Windy Path
Description

Consider following along the path in the figure above, starting from \((4,4)\) and moving to \((2,5)\). Then the path turns rightward toward \((1,6)\), then sharp left to \((5,0)\) and finally sharp left again to \((4,2)\). If we use ‘\(L\)’ for left and ‘RR’ for right, we see that the sequence of turn directions is given by RLL. Notice that the path does not cross itself: the only intersections of segments are the connection points along the path.
Consider the reverse problem: Given points in an arbitrary order,say \((2,5),(1,6),(4,4),(5,0),(4,2)\),could you find an ordering of the points so the turn directions along the path are given by RLL? Of course to follow the path in the figure,you would start with the third point in the list \((4,4)\),then the first \((2,5)\),second \((1,6)\), fourth \((5,0)\), and fifth \((4,2)\), so the permutation of the points relative to the given initial order would be: \(3\ 1 \ 2 \ 4 \ 5\).
Input
The first line of the input contains an integer \(N\), specifying the number of points such that \(3 \le N \le 50\). The following NN lines each describe a point using two integers \(x_i\) and \(y_i\) such that \(0 \le x_i,y_i \le 1000\). The points are distinct and no three are collinear (i.e., on the same line). The last line contains a string of \(N - 2\) characters, each of which is either ‘\(L\)’ or ‘\(R\)’.
Output
A permutation of\(\{ 1,...,N \}\) that corresponds to a nonintersecting path satisfying the turn conditions. The numbers are to be displayed with separating spaces. (There are always one or more possible solutions, and any one may be used.)
Solution
题意
给定 \(n\) 个点的坐标和一个包含 \(R\) 和 \(L\) 的序列,其中 \(L\) 代表左转,\(R\) 代表右转,求一个访问每个点顺序满足给定的序列。
题解
贪心 构造 计算几何
由于是 special judge,只要想出一种构造方法就可以。本题可以贪心。
- 首先选择最下面最左边的点作为起点,(起点不唯一,比如最左边最下面也可以)。
- 如果第一个字符是 \(R\),第二个点选择最左边的点;反之选择最右边的点。
- 之后每次考察连续两个字符:
- 如果是 \(RL\),选择右边最后一个
- 如果是 \(LR\),选择左边最后一个
- 如果是 \(RR\),选择右边第一个
- 如果是 \(RR\),选择左边第一个
判断点是在向量的左边还是右边可以用 \(ToLeftTest\),查询第一个还是最后一个可以用夹角判断。
/*
思路:
贪心
1. R: 左边第一个
2. L: 右边第一个
3. RL: 右边最后一个
4. LR: 左边最后一个
5. LL: 左边第一个
6. RR: 右边第一个
*/
#include <bits/stdc++.h>
using namespace std;
struct Point {
int x, y, index;
} p[100];
int area2(Point p, Point q, Point s) {
return p.x * q.y - p.y * q.x + q.x * s.y - q.y * s.x + s.x * p.y - s.y * p.x;
}
// 判断某个点在向量的左边还是右边
bool toLeftTest(Point p, Point q, Point s) {
return area2(p, q, s) > 0;
}
int cmp(Point p1, Point p2) {
if (p1.y == p2.y)
return p1.x < p2.x;
return p1.y < p2.y;
}
// 求向量 pq 与 向量 ps 之间的夹角
double ang(Point p, Point q, Point s) {
double x1 = q.x - p.x, y1 = q.y - p.y;
double x2 = s.x - p.x, y2 = s.y - p.y;
double ans = (x1 * x2 + y1 * y2) / (sqrt(x1 * x1 + y1 * y1) * sqrt(x2 * x2 + y2 * y2));
return acos(ans);
}
vector<Point> ans; // 存放答案
int vis[100]; // 标记已访问过的点
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d%d", &p[i].x, &p[i].y);
p[i].index = i;
}
sort(p + 1, p + n + 1, cmp);
ans.push_back(p[1]); // 起点
vis[p[1].index] = 1;
double min_ang = 10;
int min_index = 1;
Point tmp, tmp2 = p[1]; // 保存上两个点
string str;
cin >> str;
// 第一个点
if (str[0] == 'R') {
tmp.x = p[1].x - 1;
tmp.y = p[1].y;
for (int i = 2; i <= n; ++i) {
double angle = ang(p[1], p[i], tmp);
if (angle < min_ang) {
min_ang = angle;
min_index = i;
}
}
ans.push_back(p[min_index]);
vis[p[min_index].index] = 1;
} else {
tmp.x = p[1].x + 1;
tmp.y = p[1].y;
for (int i = 2; i <= n; ++i) {
double angle = ang(p[1], p[i], tmp);
if (angle < min_ang) {
min_ang = angle;
min_index = i;
}
}
ans.push_back(p[min_index]);
vis[p[min_index].index] = 1;
}
tmp = p[min_index];
// 之后的点
for (int i = 0; i < str.size() - 1; ++i) {
if (str[i] == 'R' && str[i + 1] == 'L') {
min_ang = 10;
for (int i = 1; i <= n; ++i) {
if (vis[p[i].index])
continue;
if (toLeftTest(tmp2, tmp, p[i]))
continue;
double angle = ang(tmp, tmp2, p[i]);
if (min_ang > angle) {
min_ang = angle;
min_index = i;
}
}
ans.push_back(p[min_index]);
vis[p[min_index].index] = 1;
tmp2 = tmp;
tmp = p[min_index];
}
else if (str[i] == 'R' && str[i + 1] == 'R') {
min_ang = 0;
for (int i = 1; i <= n; ++i) {
if (vis[p[i].index])
continue;
if (toLeftTest(tmp2, tmp, p[i]))
continue;
double angle = ang(tmp, tmp2, p[i]);
if (min_ang < angle) {
min_ang = angle;
min_index = i;
}
}
ans.push_back(p[min_index]);
vis[p[min_index].index] = 1;
tmp2 = tmp;
tmp = p[min_index];
} else if (str[i] == 'L' && str[i + 1] == 'R') {
min_ang = 10;
for (int i = 1; i <= n; ++i) {
if (vis[p[i].index])
continue;
if (!toLeftTest(tmp2, tmp, p[i]))
continue;
double angle = ang(tmp, tmp2, p[i]);
if (min_ang > angle)
{
min_ang = angle;
min_index = i;
}
}
ans.push_back(p[min_index]);
vis[p[min_index].index] = 1;
tmp2 = tmp;
tmp = p[min_index];
} else {
min_ang = 0;
for (int i = 1; i <= n; ++i) {
if (vis[p[i].index])
continue;
if (!toLeftTest(tmp2, tmp, p[i]))
continue;
double angle = ang(tmp, tmp2, p[i]);
if (min_ang < angle) {
min_ang = angle;
min_index = i;
}
}
ans.push_back(p[min_index]);
vis[p[min_index].index] = 1;
tmp2 = tmp;
tmp = p[min_index];
}
}
// 最后一个点
for (int i = 1; i <= n; ++i) {
if (!vis[p[i].index]) {
ans.push_back(p[i]);
break;
}
}
for (int i = 0; i < ans.size(); ++i) {
printf("%d", ans[i].index);
printf("%s", i == ans.size() - 1 ? "\n" : " ");
}
return 0;
}
2016 ICPC Mid-Central USA Region J. Windy Path (贪心)的更多相关文章
- 2016 ICPC总结
2016 ICPC总结 九月份开学,开始知识点的补充,刚开始的几周都在刷acmsteps,十月开始进行专题性的学习,首先进行的数据结构,给自己定的计划,十一月前看完数据结构,刚开始的时候看的都是以前的 ...
- HYNB Round 8: 2016 ICPC Amritapuri Regionals
HYNB Round 8: 2016 ICPC Amritapuri Regionals A - Tim and BSTs 做法 经典的树 DP 问题. \(dp[u][i]\) 表示考虑以 u 为根 ...
- ICPC North Central NA Contest 2018
目录 ICPC North Central NA Contest 2018 1. 题目分析 2. 题解 A.Pokegene B.Maximum Subarrays C.Rational Ratio ...
- ICPC Mid-Central USA Region 2019 题解
队友牛逼!带我超神!蒟蒻的我还是一点一点的整理题吧... Dragon Ball I 这个题算是比较裸的题目吧....学过图论的大概都知道应该怎么做.题目要求找到七个龙珠的最小距离.很明显就是7个龙珠 ...
- 2016 ICPC青岛站---k题 Finding Hotels(K-D树)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5992 Problem Description There are N hotels all over ...
- HDU 5884 Sort -2016 ICPC 青岛赛区网络赛
题目链接 #include <iostream> #include <math.h> #include <stdio.h> #include<algorith ...
- 2013 ACM/ICPC Asia Regional Changsha Online J Candies
AC了,但是不知道为什么,但是恶心的不得了~最近写代码,思路都非常清晰,但是代码各种bug~T.T~说说思路吧:二分~330ms~ 小队友fribbi的思路是离线250msAC~ 预处理solve函数 ...
- ICPC 2018 南京网络赛 J Magical Girl Haze(多层图最短路)
传送门:https://nanti.jisuanke.com/t/A1958 题意:n个点m条边的路,你有k次机会将某条路上的边权变为0,问你最短路径长度 题解:最短路变形,我们需要在常规的最短路上多 ...
- 2016 ICPC大连站---F题 Detachment
题意:输入一个x,将x拆分成一些小的数(这些数不能相同,即x=a1+a2+...... ai!=aj when i!=j),然后这些数相乘得到一个成积(s=a1*a2*......),求最大的乘积 ...
随机推荐
- hci_ceph安装过程
auto loiface lo inet loopbackauto enp50s0f0iface enp50s0f0 inet static address 192.168.1.6 netmask 2 ...
- jquery 找到指定父级指定子集
其中 closest() : jquery 1.3 新增 从元素本身开始,逐级向上级元素匹配,并返回最先匹配的元素. 其中 find() : 搜索所有与指定表达式匹配的元素.这个函数是找出正在处理的元 ...
- C++——右值引用
1.绑定到一个将要销毁的右值的引用——移动 2.左值表达式——对象的身份:右值表达式——对象的值 ; int& r=i; int&& rr=i;//×,左值不能绑定到右值引用 ...
- JPA的入门CRUD
主要目的: 操作实体类就相当于操作数据库表 建立两个映射关系: 实体类和表的映射关系 实体类中的属性和表中字段的映射关系 不在关注sql语句 常见的orm框架:Mybatis(ibatis).Hibe ...
- html5中的拖拽功能
拖拽元素支持的事件 ondrag 应用于拖拽元素,整个拖拽过程都会调用 ondragstart 应用于拖拽元素,当拖拽开始时调用 ondragleave 应用于拖拽元素,当鼠标离开拖拽元素是调用 on ...
- css篇-简化版
[CSS篇]简化版 (1) CSS盒模型 CSS盒模型 题目:谈谈你对CSS盒模型的认识 1) 基本概念:标准模型+IE模型 2) 标准模型和IE模型的区别 计算宽度和 ...
- jumpserver注意事项以及报错处理
需要注意下面亮点 在使用jumpserver过程中,有一步是系统用户推送,要推送成功,client(后端服务器)要满足以下条件: 后端服务器需要有python.sudo环境才能使用推送用户,批量命令等 ...
- 硬RAID与软RAID的区别
什么是RAID? RAID是英文Redundant Array of Independent Disks的缩写,翻译成中文即为独立磁盘冗余阵列,或简称磁盘阵列.简单的说,RAID是一种把多块独立的硬盘 ...
- vue - blog开发学习3
1.添加less 和less-loader支持 npm install less less-loader --save-dev 2.新建main.less,将这个样式添加到home.vue中的cont ...
- InnoDB中没有主键是如何运转的
本文章翻译自 https://blog.jcole.us/2013/05/02/how-does-innodb-behave-without-a-primary-key/ 原文作者的创作背景 一个下午 ...