UVA 10089 Repackaging


  1. 转化为 2D 求点是否在凸包内的问题。一个包装规格定义一个 2 维平面的向量(S2 - S1,S3 - S1),所求的就是这些向量组成的多边形是否包含原点(0,0),如果包含原点,则有非负整数解,否则无非负整数解。如果无解,向量都严格在经过原点的某条直/线的半平面内。可以采用判断两个相邻向量之间的夹角,如果任意两个向量的夹角都不超过PI 弧度,则方程有解,否则无解。考虑有 n 个向量 V1 - Vn,按向量与 X 轴成角的大小从小到大排列,若相邻向量的夹角在 PI弧度以内,则可以将多余的向量去掉,留下三个向量,设为 W1,W2,W3,则一定有某个向量处于两外两个向量的中间,假设为 W2 处于W1 和 W3 中间,则可以找到适当的非负系数使得 x * W1 + y * W3 的和与 -W3 相等。系数是有理数,可以乘以相应的数使得 x 和 y 变成整数。

    注意解题过程中应选择 long long 型整数以避免溢出。
    使用set,复杂度O(nlogn),time:0ms
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <set>
    using namespace std;
    struct node{
       long long x,y;  //******************
       bool operator<(node u) const{
         if (y*u.y<=0){//*********long long
            if (y==0 && u.y==0) return x<u.x;
            else return y<u.y;
         } else return (x*u.y-u.x*y)>0;   //**************************
       }
    };
    long long cross(node a,node b){
         return a.x*b.y-b.x*a.y;
    }
    long long dot(node a,node b){
        return a.x*b.x+a.y*b.y;
    }
    set<node> s;
    node p[1010];
    int main()
    {
        int n,x,y,z,i,flag;
        node t,u,v;
        set<node>::iterator l,r,now;
        while(scanf("%d",&n)!=-1){
            if (n==0) break;
            s.clear();
            for (i=1;i<=n;i++){
                scanf("%d %d %d",&x,&y,&z);
                p[i].x=y-x;p[i].y=z-x;
                s.insert(p[i]);
                //cout<<s.size()<<endl;
            }
            flag=0;
            //cout<<s.size()<<endl;
            if (s.size()==2){            //***************************Set may degenerate!
              //for (set<node>::iterator j=s.begin();j!=s.end();j++) cout<<(*j).x<<' '<<(*j).y<<endl;
              u=*(s.begin());r=s.end();r--;v=(*r);
              if (cross(v,u)==0 && dot(v,u)<0) flag=1;
            }
            for (i=1;s.size()>2 && i<=n;i++){
               t=p[i];
               s.erase(p[i]);
               p[i].x=-p[i].x;p[i].y=-p[i].y;
               now=s.lower_bound(p[i]);
               if (now==s.begin()) {
                    l=now;
                    r=s.end();
               } else {
                 if (now==s.end()){
                    now--;r=now;l=s.begin();
                 }
                 else {
                  l=now;r=now;--r;
                 }
               }
               u=*l;v=*r;
               if (cross(p[i],u)==0 && dot(p[i],u)>0) flag=1;
               if (cross(p[i],v)==0 && dot(p[i],v)>0) flag=1;
               if (cross(v,u)>0 && cross(v,p[i])>0 && cross(p[i],u)>0) flag=1;
               s.insert(t);
               if (flag) break;
            }
            if (flag) printf("Yes\n");
            else printf("No\n");
        }
        return 0;
    }
    

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在信号处理领域,DOA(Direction of Arrival)估计是一项关键技术,主要用于确定多个信号源到达接收阵列的方向。本文将详细探讨三种ESPRIT(Estimation of Signal Parameters via Rotational Invariance Techniques)算法在DOA估计中的实现,以及它们在MATLAB环境中的具体应用。 ESPRIT算法是由Paul Kailath等人于1986年提出的,其核心思想是利用阵列数据的旋转不变性来估计信号源的角度。这种算法相比传统的 MUSIC(Multiple Signal Classification)算法具有较低的计算复杂度,且无需进行特征值分解,因此在实际应用中颇具优势。 1. 普通ESPRIT算法 普通ESPRIT算法分为两个主要步骤:构造等效旋转不变系统和估计角度。通过空间平移(如延时)构建两个子阵列,使得它们之间的关系具有旋转不变性。然后,通过对子阵列数据进行最小二乘拟合,可以得到信号源的角频率估计,进一步转换为DOA估计。 2. 常规ESPRIT算法实现 在描述中提到的`common_esprit_method1.m`和`common_esprit_method2.m`是两种不同的普通ESPRIT算法实现。它们可能在实现细节上略有差异,比如选择子阵列的方式、参数估计的策略等。MATLAB代码通常会包含预处理步骤(如数据归一化)、子阵列构造、旋转不变性矩阵的建立、最小二乘估计等部分。通过运行这两个文件,可以比较它们在估计精度和计算效率上的异同。 3. TLS_ESPRIT算法 TLS(Total Least Squares)ESPRIT是对普通ESPRIT的优化,它考虑了数据噪声的影响,提高了估计的稳健性。在TLS_ESPRIT算法中,不假设数据噪声是高斯白噪声,而是采用总最小二乘准则来拟合数据。这使得算法在噪声环境下表现更优。`TLS_esprit.m`文件应该包含了TLS_ESPRIT算法的完整实现,包括TLS估计的步骤和旋转不变性矩阵的改进处理。 在实际应用中,选择合适的ESPRIT变体取决于系统条件,例如噪声水平、信号质量以及计算资源。通过MATLAB实现,研究者和工程师可以方便地比较不同算法的效果,并根据需要进行调整和优化。同时,这些代码也为教学和学习DOA估计提供了一个直观的平台,有助于深入理解ESPRIT算法的工作原理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值