• 计算几何 poj 3347


    题意:依次给出n个正方形的边长,要求在第一象限内依次放入正方形,满足:

    ①放入第i个正方形时,第i个正方形与前面的正方形都不重合

    ②放入正方形时,要求一个顶点在x轴上,且坐标值最小

    其实看这个图就懂规则了

    求放完所有正方形后,从高处向下照射竖直平行光,有部分会被照亮的正方形序号。

    题解:

    该题事实上只用到投影长度,将数据放大根号2倍,显然结果不变,但就只涉及整数计算,避免了精度问题

    设正方形边长为s[i]=读入数据*根号2,顶点坐标为t[i]

    考虑两件事——如何放正方形和如何判断是否被照亮:

    放置①放第i个正方形的时候,扫描前i-1个正方形,now=max{s[k]+2*min{s[k],s[i]}},t[i]=max{now,s[i]}

    判断②对第i个正方形,扫描1~i-1个正方形,l=max{s[j]+s[i]-(t[i]-t[j])},扫描i+1~n个正方形,r=max(r,s[j]+s[i]-(t[j]-t[i])),如果l+r<2*s[i],这个正方形就有被照亮的地方

    写这种水题的时候常会失智,莫名写上半天

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    
    int n,k,now,r,l;
    int s[100],t[100];
    int main()
    {
        while (~scanf("%d",&n))
        {
            if (n==0) break;
            rep(i,1,n)
                scanf("%d",s+i);
            t[1]=s[1];
            rep(i,2,n)
            {
                now=0;
                rep(j,1,i-1) now=max(now,t[j]+2*min(s[i],s[j]));
                now=max(now,s[i]);
                t[i]=now;
            }
            rep(i,1,n)
            {
                l=0;r=0;
                rep(j,1,i-1) if (s[j]>s[i])
                    l=max(l,s[j]+s[i]-(t[i]-t[j]));
                rep(j,i+1,n) if (s[j]>s[i])
                    r=max(r,s[j]+s[i]-(t[j]-t[i]));
                if (l+r<2*s[i]) printf("%d ",i);
            }
            printf("
    ");
        }
    }
  • 相关阅读:
    【设计模式】策略模式
    【设计模式】模板方法模式
    【C++】《Effective C++》第五章
    【C++】《Effective C++》第四章
    free命令详解(内存)
    top命令详解(动态进程)
    ps命令详解(静态进程)
    SpringBoot_集成Redis
    SpringBoot_热部署插件
    SpringBoot_实现RESTfull API
  • 原文地址:https://www.cnblogs.com/terra/p/7067517.html
Copyright © 2020-2023  润新知