zoukankan      html  css  js  c++  java
  • 平行x 轴的线段 是否 遮掩 计算几何的扩大数据运算的典型应用,扩大根号2倍之后就避免了小数。 poj 3347 Kadj Squares

    题目来源: http://poj.org/problem?id=3347

    题意:变长不同的n个正方形,斜45度按顺序平放在坐标轴上,尽量靠左但不能跃出x=0,问从上往下看,哪些正方形是可见的。

    题解:1、假如前i-1个正方形位置都确定了,那么可以让第i个正方形与前i-1个正方形每个都计算一次它如果和它相依靠的话左边顶点坐标的值,然后取一个最大的便是这个正方形的左端点位置。  这个结论 需要仔细推敲。

       2、对于j<i的正方形,如果i的边长大于j那么j的最右能看到的部分就不会比i的最左端点大,反之,i的最左能看到的部分就不会比j最右端点小。

       3、通过第2步筛选,将那些最左能看到的端点比最右能看到端点大或等于的去掉,剩下的就是所要求的。

    4: 注意 ,我们 存放 正方形 端点的坐标时,  是将坐标轴 扩大 √2 倍。

    代码如下:

      

    #include <iostream>
    #include <algorithm>
    #include <stdlib.h>
    #include <iostream>
    #include <stdio.h>
    #include <string>
    #include <string.h>
    #include <vector>
    #include <set>
    #include <math.h>
    #include <cmath>
    #include <map>
    #include <queue>
    
    using namespace std;
    typedef long long ll;
    const int N =60;
    struct Line
    {
        int left;
        int right;
        int length;
    };
    int n;
    Line line[N];
    int side[N];
    void solve()
    {
    
    }
    int main()
    {
        while(cin>>n && n)
        {
            cin>>side[0];
            line[0].left=0;
            line[0].right=2*side[0];  // 坐标轴 扩大 √2 倍
            line[0].length=2*side[0];
            for (int i=1;i<n ;i++)
            {
                cin>> side[i];
                int left=0;
                for(int j=i-1 ;j>=0; j--)
                    left=max(left, line[j].right-abs(side[i]-side[j]) );    // 第i 个 正方形的左端点的 x位置 是 与 前 i-1 个正方形依靠的 最大 x 值
                line[i].left=left;
                line[i].right=line[i].left+2*side[i];
                line[i].length=2*side[i];
            }
            for(int i=1 ;i<n;i++)
            {
                for(int j=0; j<i;j++)
                {
                    if(line[i].length < line[j].length && line[i].left < line[j].right)  // 更新左右端点的值
                        line[i].left=line[j].right;
                    if(line[i].length > line[j]. length && line[i].left < line[j].right )
                        line[j].right=line[i].left;
                }
            }
            int count=0;
            for(int i=0 ;i<n ;i++)
            {
                if(line[i].left < line[i].right)   
                {
                    if(count)
                        printf(" ");
                    printf("%d",i+1);
                    count=1;
                }
            }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    python中的 if __name__ == "__main__": 语句的作用
    python的打包与解包
    python循环删除列表元素
    python字典键值对新增与修改的几种方法及差异总结
    python列表元素删除的几种方法以及差异总结
    python之redis(二)
    python之redis(一)
    python之mysql(四)
    python之mysql(三)
    python之mysql(二)
  • 原文地址:https://www.cnblogs.com/zn505119020/p/3628332.html
Copyright © 2011-2022 走看看