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*......),求最大的乘积 ...
随机推荐
- javascript函数调用的几种方式
function fn() { console.log(this.name); return "fn函数的返回值"; } /*1.方法调用*/ //方法调用,this指向win ...
- 11-vim-撤销和删除命令-01-撤销
撤销和恢复撤销 命令 英文 功能 u undo 撤销上一次命令 ctrl u redo 恢复撤销的命令
- Json解析之FastJson
版权声明:转载请注明出处 https://blog.csdn.net/heqiangflytosky/article/details/37659943 1.FastJson介绍 FastJson是阿里 ...
- TurtleBOT3
ubuntu更换源 sudo cp /etc/apt/sources.list /etc/apt/sources_backup.list sudo gedit /etc/apt/sources.lis ...
- springboot整合RocketMq(非事务)
1.配置文件 1.yml配置文件 rocketmq: #mq配置 producer: iseffect: true type: default # (transaction,default) tran ...
- 在egg中配置 sequelize
如何在eggjs中引入 sequlize 安装 第一步,在项目中安装 egg-sequelize插件和mysql插件 npm install --save egg-sequelize mysql2 第 ...
- SpringMVC 与axis2 的整合(服务器端)
1,新建一个web project项目,项目的目录 如下: 2,导入需要的jar包,本例用的是axis2 1.7.3版本. 3,创建接口. package com.dsdl.hcm.webServic ...
- teb教程1
http://wiki.ros.org/teb_local_planner/Tutorials/Setup%20and%20test%20Optimization 简介:本部分关于teb怎样优化轨迹以 ...
- MYSQL增量备份与恢复
vim /etc/my.cnf在[mysqld]下添加max_binlog_size = 1024000 //二进制日志最大1M 要进行mysql的增量备份,首先要开启二进制日志功能方法一:在/etc ...
- Codeforces 343E 最小割树
题意及思路:https://www.cnblogs.com/Yuzao/p/8494024.html 最小割树的实现参考了这篇博客:https://www.cnblogs.com/coder-Uran ...