URAL 1990 Podracing

本文深入解析了一个计算几何问题,即如何在两条垂直折线间,找到从一条直线段到另一条直线段的最长距离,同时避免穿过指定的摄像头。通过高效算法处理折线点之间的距离以及摄像头与折线的距离,最终实现最优解的求取。文章详细介绍了算法步骤,包括点的处理、距离计算以及最终答案的优化过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

计算几何。。首先题意很难懂,多亏了纬哥解释,才懂。。

就是有左边有一条折线,右边有一条折线,两条折线的起点和终点的纵坐标相同,还有一些摄像头,一条线段平行x轴的线段从起点到终点,必须得在两条折线中间,并且不能碰到摄像头,问线段最长的长度

其实不难的,思路很快就有了,先o(n)处理左边折线的点到右边的折线的水平长度以及右边的点到左边的点的长度,然后再求摄像头到左右两条折线的水平长度。。不过wa了,我们很快发现了错误在哪,就是摄像头的纵坐标有可能相同,还有y轴坐标大于或者小于折线的终点和起点的摄像头都不能算进去,不过最后还是写挫了,没有ac,今天终于ac了。。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <map>
  7 
  8 using namespace std;
  9 
 10 #define LL long long
 11 #define eps 1e-12
 12 #define mnx 100020
 13 #define mxe 2000020
 14 #define inf 1e12
 15 #define Pi acos( -1.0 )
 16 
 17 //精度
 18 int dcmp( double x ){
 19     if( fabs( x ) < eps ) return 0;
 20     return x < 0 ? -1 : 1;
 21 }
 22 //
 23 struct point{
 24     double x, y;
 25     point( double x = 0, double y = 0 ) : x(x), y(y) {}
 26     point operator + ( const point &b ) const{
 27         return point( x + b.x, y + b.y );
 28     }
 29     point operator - ( const point &b ) const{
 30         return point( x - b.x, y - b.y );
 31     }
 32     point operator * ( const double &k ) const{
 33         return point( x * k, y * k );
 34     }
 35     point operator / ( const double &k ) const{
 36         return point( x / k, y / k );
 37     }
 38     bool operator < ( const point &b ) const{
 39         return dcmp( y - b.y ) < 0 || dcmp( y - b.y ) == 0 && dcmp( x - b.x ) < 0;
 40     }
 41     bool operator == ( const point &b ) const{
 42         return dcmp( x - b.x ) == 0 && dcmp( y - b.y ) == 0;
 43     }
 44     double len(){
 45         return sqrt( x * x + y * y );
 46     }
 47     void input(){
 48         scanf( "%lf%lf", &x, &y );
 49     }
 50 };
 51 typedef point Vector;
 52 // 点积
 53 double dot( Vector a, Vector b ){
 54     return a.x * b.x + a.y * b.y;
 55 }
 56 // 叉积
 57 double cross( Vector a, Vector b ){
 58     return a.x * b.y - a.y * b.x;
 59 }
 60 int n, m, q;
 61 point a[mnx], b[mnx], c[mnx];
 62 double calc( point p0, point p1, point p2  ){
 63     if(dcmp(p1.y - p2.y) == 0) {
 64         return min((p0 - p1).len(), (p0 - p2).len());
 65     }
 66     if( p1.y > p2.y ) swap( p1, p2 );
 67     double t = (p0.y - p1.y) / ( p2.y - p1.y );
 68     point v = p1 + ( p2 - p1 ) * t;
 69     return ( p0 - v ).len();
 70 }
 71 void solve(){
 72     double ans = inf;
 73     int j = 0;
 74     for( int i = 0; i < n; i++ ){
 75         while( j < m-1 ){
 76             if( dcmp(a[i].y-b[j].y) >= 0 && dcmp(a[i].y-b[j+1].y) <= 0 ){
 77                 ans = min( ans, calc( a[i], b[j], b[j+1] ) );
 78                 break;
 79             }
 80             else j++;
 81         }
 82     }
 83     j = 0;
 84     for( int i = 0; i < m; i++ ){
 85         while( j < n-1 ){
 86             if( dcmp(b[i].y-a[j].y) >= 0 && dcmp(b[i].y-a[j+1].y) <= 0 ){
 87                 ans = min( ans, calc( b[i], a[j], a[j+1] ) );
 88                 break;
 89             }
 90             else j++;
 91         }
 92     }
 93     sort( c, c + q );
 94     int cnt = 0;
 95     for( int i = 0; i < q; i++ ){
 96         if( dcmp(c[i].y-a[0].y) < 0 || dcmp(c[i].y-a[n-1].y) > 0 ) continue;
 97         c[cnt++] = c[i];
 98     }
 99     q = cnt;
100     int i = 0; j = 0;
101     for( int k = 0; k < q; k++ ){
102         double res = -inf;
103         int cur = k;
104         while( cur < q && dcmp(c[cur+1].y - c[cur].y) == 0 ) cur++;
105         int tmp = cur;
106 
107         while( i < n-1 ){
108             if( dcmp(c[k].y-a[i].y) >= 0 && dcmp(c[k].y-a[i+1].y) <= 0 )
109                 break;
110             else i++;
111         }
112         while( j < m-1 ){
113             if( dcmp(c[k].y-b[j].y) >= 0 && dcmp(c[k].y-b[j+1].y) <= 0 )
114                 break;
115             else j++;
116         }//cout << k << " " << cur << endl;
117         for( int u = k; u < cur; u++ ){
118             if( cross( c[u] - a[i], a[i+1] - a[i] ) < 0 ) k++;
119             else break;
120         }
121         for( int u = cur; u > k; u-- ){
122             if( cross( c[u] - b[j], b[j+1] - b[j] ) > 0 ) cur--;
123             else break;
124         }
125         res = max( res, calc( c[k], a[i], a[i+1] ) );
126         res = max( res, calc( c[cur], b[j], b[j+1] ) );
127         //printf( "%.5lf\n", res );
128         for( int u = k; u < cur; u++ ){
129             res = max( res, ( c[u+1] - c[u] ).len() );
130         }
131         ans = min( res, ans );
132         k = tmp;
133     }
134     printf( "%.8lf\n", ans );
135 }
136 int main(){
137     while( scanf( "%d", &n ) != EOF ){
138         for( int i = 0; i < n; i++ )
139             a[i].input();
140         scanf( "%d", &m );
141         for( int i = 0; i < m; i++ )
142             b[i].input();
143         scanf( "%d", &q );
144         for( int i = 0; i < q; i++ )
145             c[i].input();
146         solve();
147     }
148     return 0;
149 }
View Code

 

附数据

4
0 0
5 5
9 12
8 15
4
8 0
11 7
12 10
12 15
7
7 4
5 8
6 8
9 8
11 8
14 8
16 8

answer: 2.28571429

转载于:https://www.cnblogs.com/LJ-blog/p/4023080.html

变分模态分解(Variational Mode Decomposition, VMD)是一种强大的非线性、无参数信号处理技术,专门用于复杂非平稳信号的分析与分解。它由Eckart Dietz和Herbert Krim于2011年提出,主要针对传统傅立叶变换在处理非平稳信号时的不足。VMD的核心思想是将复杂信号分解为一系列模态函数(即固有模态函数,IMFs),每个IMF具有独特的频率成分和局部特性。这一过程与小波分析或经验模态分解(EMD)类似,但VMD通过变分优化框架显著提升了分解的稳定性和准确性。 在MATLAB环境中实现VMD,可以帮助我们更好地理解和应用这一技术。其核心算法主要包括以下步骤:首先进行初始化,设定模态数并为每个模态分配初始频率估计;接着采用交替最小二乘法,通过交替最小化残差平方和以及模态频率的离散时间傅立叶变换(DTFT)约束,更新每个模态函数和中心频率;最后通过迭代优化,在每次迭代中优化所有IMF的幅度和相位,直至满足停止条件(如达到预设迭代次数或残差平方和小于阈值)。 MATLAB中的VMD实现通常包括以下部分:数据预处理,如对原始信号进行归一化或去除直流偏置,以简化后续处理;定义VMD结构,设置模态数、迭代次数和约束参数等;VMD算法主体,包含初始化、交替最小二乘法和迭代优化过程;以及后处理,对分解结果进行评估和可视化,例如计算每个模态的频谱特性,绘制IMF的时频分布图。如果提供了一个包含VMD算法的压缩包文件,其中的“VMD”可能是MATLAB代码文件或完整的项目文件夹,可能包含主程序、函数库、示例数据和结果可视化脚本。通过运行这些代码,可以直观地看到VMD如何将复杂信号分解为独立模态,并理解每个模态的物理意义。 VMD在多个领域具有广泛的应用,包括信号处理(如声学、振动、生物医学信号分析)、图像处理(如图像去噪、特征提取)、金融时间序列分析(识
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值