sysu-1,ural1894,闽科夫斯基和(黑科技)

茶杯 茶杯     2022-07-31     727

关键词:

题目大题:给你两个相交的凸包,其中一个可移动,问你至少移动多少能够让两个凸包分离

解:我艹我为此写了7k计算几何还是wa6了,后面去看discuz才知道是用一个闽科夫斯基和的黑科技。

闽科夫斯基和大概就是两个点集的任意两个点对相加得到的一个新点集,差则是相减。这题用到了以下几个性质:

  1:两个凸包的闽科夫斯基差还是凸包

  2:两个凸包若相交,那么他们闽科夫斯基差的凸包覆盖原点

易知答案是原点到凸包最短距离(可以看作一个凸包平移这个向量,那么他们的闽科夫斯基差就不过原点了,所以相离)

现在问题在于如何快速求差的凸包(定义求是nm的)。wiki告诉我一个性质,就是新凸包的向量组织是两个旧凸包方向边的和。

所以对旧凸包一起选一个方向,然后合并他们的向量,用新向量组合按顺序扫一遍头尾相接就得到差凸包的形状。接下来就是确定位置。我大概yy了下(没有严谨证明),凡是合并之后AB相间的两个向量,他们的头尾坐标和必定是差凸包那个点的原坐标,所以我们比对一下位置凸包这个点的坐标和实际坐标的差平移一下即可。

 

#include <cstdio>
#include <string>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <complex>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <deque>

using namespace std;

const double EPS = 1e-8;

#define ABS(x) ((x)<0?(-(x)):(x))
#define SQR(x) ((x)*(x))
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))

#define LSON(x) ((x)<<1)
#define RSON(x) (((x)<<1)+1)
#define LOWBIT(x) ((x)&(-(x)))
#define MAXN 111111
#define LL long long

int cmp(const double &x) {
    return x < -EPS ? -1 : (x > EPS ? 1 : 0);
}

struct point{
    double x, y;
    point(double a = 0, double b = 0): x(a), y(b) {}

    point operator + (const point &rhs) const {
        return point(x + rhs.x, y + rhs.y);
    }
    point operator - (const point &rhs) const {
        return point(x - rhs.x, y - rhs.y);
    }
    point operator * (const double &rhs) const {
        return point(x * rhs, y * rhs);
    }
    point operator / (const double &rhs) const {
        return point(x / rhs, y / rhs);
    }
    bool operator < (const point &rhs) const {
        if (cmp(x - rhs.x) == 0) return y < rhs.y;
        return x < rhs.x;
    }

    void read() {
        scanf("%lf%lf", &x, &y);
    }
    void write() const {
        printf("%lf %lf\n", x, y);
    }
    double norm() const {
        return sqrt(SQR(x) + SQR(y));
    }
};

double dot(const point &a, const point &b) {
    return a.x * b.x + a.y * b.y;
}

double det(const point &a, const point &b) {
    return a.x * b.y - a.y * b.x;
}

typedef point Point;
//#define Point point
typedef pair<Point, Point > Halfplane;
typedef vector<Point > Convex;

inline double arg(const point &a) {
    double res = atan2(a.y, a.x);
    return res;
}

#define cross(a,b) det(a,b)

void PointProjLine(const point &p, const point &s, const point &t, point &cp) {
    double r = dot((t-s), (p-s))/dot(t-s, t-s);
    cp = s + (t - s) * r;
}

int n, m;
Convex a, b, c;
double ans;

struct data{
    double a;
    point st, ed;
    int col;
    data() {}
    data(double aa, point b, point c, int d): a(aa), st(b), ed(c), col(d) {}
    bool operator < (const data &rhs) const {
        return a < rhs.a;
    }
};

vector <data > aa;
vector <point > key;

const double PI = acos(-1);

void init() {
    double ans = 1e30;
    Point x;
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; ++i) {
        x.read(); a.push_back(x);
    } a.push_back(a[0]);

    for (int i = 0; i < n; ++i) {
        aa.push_back(data(arg((a[i+1] - a[i])) + 2 * PI, a[i], a[i+1], 0));
    }

    for (int i = 0; i < m; ++i) {
        x.read(); b.push_back(x*-1);
    } b.push_back(b[0]);
    for (int i = 0; i < m; ++i) {
        aa.push_back(data(arg((b[i+1] - b[i])) + 2 * PI, b[i], b[i+1], 1));
    }
    sort(aa.begin(), aa.end());
}

double dist(const point &p, const point &s, const point &t) {
    point tt;
    PointProjLine(p, s, t, tt);
    return (p - tt).norm();
}

void solve() {
    point now = point(0, 0);
    aa.push_back(aa[0]);
    for (int i = 0; i < n+m; ++i) {
        now = now + (aa[i].ed - aa[i].st);
        key.push_back(now);
    }
    point dd;
    key.push_back(key[0]);

    for (int i = 0; i + 1 < n+m; ++i) {
        if (aa[i].col != aa[i+1].col) {
            dd = (aa[i].ed + aa[i+1].st) - key[i];
            break;
        }
    }
    for (int i = 0; i < key.size(); ++i) {
        key[i] = key[i] + dd;
    }
    ans = 1e30;
    for (int i = 0; i < n+m; ++i) {
        ans = min(ans, dist(point(0, 0), key[i], key[i+1]));
    }
}


int main() {
    freopen("test.txt", "r", stdin);
    init();
    solve();
    if (ans < 60) puts("0");
    else printf("%.8lf\n", max(0.0, ans - 60));
    return 0;
}
ural 1894

 

中闽在线:以“积分”为纽带共享线上渠道资源

...现如今有物流供应链平台、有金融供应链平台,也有像中闽在线这样的综合性供应链服务商。中闽在线是由从事电商代理服务、供应链、系统建设及运营为一体的中闽在线(厦门)电子商务有限公司所创建,从2014年成立到现在,目前已... 查看详情

[m前缀和]lc1894.找到需要补充粉笔的学生编号(二分+模拟+坑点)(代码片段)

文章目录1.题目来源2.题目解析1.题目来源链接:1894.找到需要补充粉笔的学生编号2.题目解析有个坑点,有点恶心。首先被数据坑一把,需要开LL,然后被边界坑一把…先求前缀和,然后k对a[n-1]取模,然后... 查看详情

[m前缀和]lc1894.找到需要补充粉笔的学生编号(二分+模拟+坑点)(代码片段)

文章目录1.题目来源2.题目解析1.题目来源链接:1894.找到需要补充粉笔的学生编号2.题目解析有个坑点,有点恶心。首先被数据坑一把,需要开LL,然后被边界坑一把…先求前缀和,然后k对a[n-1]取模,然后... 查看详情

python计算闵科夫斯基和(代码片段)

找了半天网上只有两种版本的计算闵科夫斯基和夏天大佬的c++闵科夫斯基和这个大佬的闵科夫斯基和更好理解饕餮传奇大佬的c++闵科夫斯基和这个大佬讲的更加细致,同时他的博客里还有很多其他的数学计算的讲... 查看详情

python计算闵科夫斯基和(代码片段)

找了半天网上只有两种版本的计算闵科夫斯基和夏天大佬的c++闵科夫斯基和这个大佬的闵科夫斯基和更好理解饕餮传奇大佬的c++闵科夫斯基和这个大佬讲的更加细致,同时他的博客里还有很多其他的数学计算的讲... 查看详情

ural-1017staircases

URAL-1017状态:dp[i][j]表示和为i最大数小于等于j的方案数初始状态:dp[0][0]=1状态转移:dp[i][j]=dp[i-j][j-1]+dp[i][j-1],i>=j第二维可以用滚动数组消掉最后减去和为n最大值也为n的情况,因为这种不满足条件代码:#include<bits/stdc++.h>... 查看详情

“丝路正青春风采看福建”在闽外籍青年短视频大赛火热征集作品中

...政府外事办公室共同主办的“丝路正青春风采看福建”在闽外籍青年短视频大赛已经启动,目前正在火热征集作品。本次大赛不限制参赛者的年龄、职业。在闽外籍青年,或曾经在闽生活工作的外籍青年均可参赛。大赛... 查看详情

ural1469

题解:从左往右加入每一个点判断一下和,pre,nxt是否相交删除得时候也要判断代码:#pragmaGCCoptimize(2)#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>usingnamespacestd;constintN=200010;typedefdoub 查看详情

ural1501senseofbeauty

URAL1501思路:dp+记忆化搜索状态:dp[i][j]表示选取第一堆前i个和第二堆前j的状态:0:0多1个             1:0和1相等           查看详情

ural2078~2089

URAL2078~2089A-Bowlinggame题目描述:给出保龄球每一局击倒的球数,按照保龄球的规则,算出总得分的最小值和最大值。solution首先是最小值:每一局第一球击倒(0)个,第二球击倒给定的数目,最后一局比较特殊,如果最后一局得分... 查看详情

ural1244gentlemen

URAL1244思路:dp,有点类似背包,不过不需要求最大价值,只要求方案数就可以了。状态:dp[i]表示和为i的方案数初始状态:dp[0]=1状态转移:dp[i]=∑dp[i-a[k]](1<=k<=n)用一个pre[]数组来记录路径代码:#include<bits/stdc++.h>usingnam... 查看详情

ural2014zhenyamovesfromparents线段树

线段树,前缀和最小ZhenyamovesfromparentsTimeLimit: 1000MS MemoryLimit: 65536KB 64bitIOFormat: %I64d&%I64uSubmit StatusDescriptionZhenyamovedfromhisparents’hometostudyinotherci 查看详情

ural-2065differentsums(思维题)(代码片段)

题意:给n和k,让你用不小于k个不同的数字构成一个长度为n的序列,使得序列中不同的区间和的数目最小。n,k<=500  k-1个数填一些数字的一正一负,这样有些区间和为0。剩下的都填0。 #include<iostream>#include<cs... 查看详情

ural1998theoldpadawan

前缀和,二分。按时间模拟,每次二分找到应该扔掉哪些。#include<map>#include<set>#include<ctime>#include<cmath>#include<queue>#include<string>#include<vector>#include<cstdio>#includ 查看详情

UDF 导致警告:CachedKafkaConsumer 未在 UninterruptibleThread 中运行 (KAFKA-1894)

】UDF导致警告:CachedKafkaConsumer未在UninterruptibleThread中运行(KAFKA-1894)【英文标题】:UDFcausewarning:CachedKafkaConsumerisnotrunninginUninterruptibleThread(KAFKA-1894)【发布时间】:2018-06-2600:16:37【问题描述】:在通常的structured_kafka_wordcount.py 查看详情

ural1707.hypnotoad'ssecret(线段树)

题目链接:ural1707.Hypnotoad‘sSecret题目大意:给定N和M,然后N组s0,t0,Δs,Δt,k,每组能够计算出k个星星的坐标;M组a0,b0,c0,d0,Δa,Δb,Δc,?Δd,q。每组要求算出q个矩形,推断矩形内是否包括星星,对于q≥20的情况要依据公式计算一个值... 查看详情

1894.找到需要补充粉笔的学生编号(代码片段)

一个班级里有 n 个学生,编号为0 到n-1 。每个学生会依次回答问题,编号为0 的学生先回答,然后是编号为1 的学生,以此类推,直到编号为n-1 的学生,然后老师会重复这个过程,重新从编号为0 ... 查看详情

1894.找到需要补充粉笔的学生编号(代码片段)

一个班级里有 n 个学生,编号为0 到n-1 。每个学生会依次回答问题,编号为0 的学生先回答,然后是编号为1 的学生,以此类推,直到编号为n-1 的学生,然后老师会重复这个过程,重新从编号为0 ... 查看详情