破阵子(三分+凸包旋转卡壳)

2023-12-06 21:12

本文主要是介绍破阵子(三分+凸包旋转卡壳),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description

平面上有n个点,每个点有各自的速度向量,现在给出0时刻,在同一时刻,平面点的最远距离叫做special dis
他们每个点的位置和每个点的速度向量,现在求在哪个时刻的时候,他们的special dis 最小,并输出这个距离。

Input

输入一个正整数T(T<=10),表示有T组数据,每组数据包括一个n(n<=10000),表示有n个点,每行包括每个点的坐标 (x,y) (-100000<=x,y<=100000),速度向量 (vx,vy)  (-1000<=vx,vy<=1000)

Output

输出在哪个时刻的时候,special dis距离最小,保留两位小数

Sample Input

2
2
0 0 1 0
2 0 -1 0
4
27 27 0 2
58 88 -8 -1
-22 7 1 -1
-38 -26 5 9

Sample Output

1.00 0.00
8.89 81.00

思路:

求最大值中最小值,首先想到二分

但发现dis不一定随时间增大而增大,

事实上,两点间距离,要么直接增加,要么先减少再增加。

所以dis也是要么直接增加,要么先减少再增加。

这是一个单峰的变化。

用到三分;

其次,对于每个时间点,我们可以知道每个点坐标。

多对点的最远距离一定是在凸包上取得的(证明可以搜搜)

找到凸包之后,用旋转卡壳求取一个时间点的最远距离;

代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
#define per(i,a,b) for(int i=a;i<=b;i++)
#define ber(i,a,b) for(int i=a;i>=b;i--)
const int N = 1e4 + 5;
const LL mod = 10000000033;
double eps = 1e-8;
int top = 0, n;
struct Point
{
    double x;
    double y;
    double vx;
    double vy;
}p[N], tmp[N], s[N];
bool cmp(struct Point a, struct Point  b)
{
    if (a.x != b.x)
        return a.x < b.x;
    return a.y < b.y;
}
void  into(double t)
{
    per(i, 1, n)
    {
        tmp[i].x = p[i].x + p[i].vx * t;
        tmp[i].y = p[i].y + p[i].vy * t;
    }
    sort(tmp + 1, tmp + 1 + n, cmp);
}
double cross(struct Point& a, struct Point& b, struct Point& c)
{
    return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}
void Andro(double t)
{
    top = -1;
    into(t);
    per(i, 1, n)
    {
        while (top > 0 && cross(s[top - 1], s[top], tmp[i]) <= 0) top--;
        s[++top] = tmp[i];
    }
    int tt = top;
    ber(i, n - 1, 1)
    {
        while (top > tt && cross(s[top - 1], s[top], tmp[i]) <= 0)  top--;
        s[++top] = tmp[i];
    }
}
double dis(struct Point& a, struct Point& b)
{
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
double f(double t)
{
    Andro(t);
    if (top <= 2)
        return dis(s[0], s[1]);
    double ans = 0;
    for (int i = 0, j = 2; i < top; i++)
    {
        while (abs(cross(s[i], s[i + 1], s[j])) < abs(cross(s[i], s[i + 1], s[j + 1]))) j = (j + 1) % top;
        ans = max(ans, max(dis(s[i], s[j]), dis(s[i + 1], s[j])));
    }
    return ans;
}
double sanfen(double l, double r)
{
    double mi, ma;
    while (r - l > eps)
    {
        mi = l + (r - l) / 3;
        ma = r - (r - l) / 3;
        if (f(mi) >= f(ma)) l = mi;
        else r = ma;
    }
    return mi;
}
int main()
{
    int T;
    cin >> T;
    while (T--)
    {
        cin >> n;
        per(i, 1, n)
            cin >> p[i].x >> p[i].y >> p[i].vx >> p[i].vy;
        double t = sanfen(0, 10000);
        printf("%.2f %.2f\n", t, f(t));
    }
    return 0;
}

这篇关于破阵子(三分+凸包旋转卡壳)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/463352

相关文章

Qt QWidget实现图片旋转动画

《QtQWidget实现图片旋转动画》这篇文章主要为大家详细介绍了如何使用了Qt和QWidget实现图片旋转动画效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 一、效果展示二、源码分享本例程通过QGraphicsView实现svg格式图片旋转。.hpjavascript

poj 1113 凸包+简单几何计算

题意: 给N个平面上的点,现在要在离点外L米处建城墙,使得城墙把所有点都包含进去且城墙的长度最短。 解析: 韬哥出的某次训练赛上A出的第一道计算几何,算是大水题吧。 用convexhull算法把凸包求出来,然后加加减减就A了。 计算见下图: 好久没玩画图了啊好开心。 代码: #include <iostream>#include <cstdio>#inclu

poj 2187 凸包or旋转qia壳法

题意: 给n(50000)个点,求这些点与点之间距离最大的距离。 解析: 先求凸包然后暴力。 或者旋转卡壳大法。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <s

Codeforces Beta Round #47 C凸包 (最终写法)

题意慢慢看。 typedef long long LL ;int cmp(double x){if(fabs(x) < 1e-8) return 0 ;return x > 0 ? 1 : -1 ;}struct point{double x , y ;point(){}point(double _x , double _y):x(_x) , y(_y){}point op

HDU 1392 HDU 1348 凸包

求凸包的周长,  注意n=1 , 2时特殊情况 int cmp(double x){if(fabs(x) < 1e-8) return 0 ;if(x > 0) return 1 ;return -1 ;}struct point{double x , y ;point(){}point(double _x , double _y):x(_x) , y(_y){}frien

Android 10.0 mtk平板camera2横屏预览旋转90度横屏拍照图片旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,在上一篇已经实现了横屏预览功能,然后发现横屏预览后,拍照保存的图片 依然是竖屏的,所以说同样需要将图片也保存为横屏图标了,所以就需要看下mtk的camera2的相关横屏保存图片功能, 如何实现实现横屏保存图片功能 如图所示: 2.mtk

二维旋转公式

二维旋转公式 ros的tf工具包可以很方便的实现任意坐标系之间的坐标转换。但是,如果只是想简单的测试想法,而又不想编写过于庞杂的代码,考虑自己写二维旋转的函数。而与二维旋转问题对偶的另一个问题便是二维坐标系旋转变换。这两个问题的形式基本一样,只是旋转的角度相差一个负号。就是这个容易搞混,所以做个笔记,以备查用。 1. 二维旋转公式(算法) 而(此文只针对二维)旋转则是表示某一坐标点 ( x

算法复杂度 —— 数据结构前言、算法效率、时间复杂度、空间复杂度、常见复杂度对比、复杂度算法题(旋转数组)

目录 一、数据结构前言 1、数据结构 2、算法 3、学习方法 二、 算法效率 引入概念:算法复杂度  三、时间复杂度 1、大O的渐进表示法 2、时间复杂度计算示例  四、空间复杂度 计算示例:空间复杂度 五、常见复杂度对比 六、复杂度算法题(旋转数组) 1、思路1 2、思路2 3、思路3 一、数据结构前言 1、数据结构         数据结构(D

【UVA】10652-Board Wrapping(凸包问题)

又增加了2个模板。 #include <iostream>#include <cstdlib>#include <cstdio>#include <string>#include <cstring>#include <cmath>#include <vector>#include <queue>#include <stack>#include <algorithm>usi

百度之星初赛1006(计算几何:能包含凸包的最小矩形面积)

矩形面积    Accepts: 717    Submissions: 1619  Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description 小度熊有一个桌面,小度熊剪了很多矩形放在桌面上,小度熊想知道能把这些