poj 3347 Kadj Squares

这个题要用到扩大数据运算,和投影;

目的意思比较奇葩,给出N个正方形, 每个正方形是都45度放置,并且每个正方形都与X轴接触。因此产生一个序列, b1 – bn 。

 

 

poj 3347 Kadj Squares

首先是插入操作,每次输入边长的时候将正方形插入到能插入的最左边, 什么意思了,结合图看一下, 就是s3本来可以插入到s1的前面,s1和s2的中间, 但最左边是s2,故插入到了s2的左边。在插入的的时候可以求得正方形的左区间和右区间,
比如说
s2.left = s1.right – fabs(s1.len – s2.len)/sqrt(2)
s2.right = s2.len + sqrt(2)*s1.left
两个计算中都有一个操作根号2的过程,
如果把边长乘以根号2,
是不是就变成了整数操作。
s2.left = s1.right – fabs(s1.len – s2.len)
s2.right = s2.len + 2*s1.left
那么区间处理就方便多了。

左右区间是用来进行投影计算的;我们知道正方形投影下来有一条直线,如果看得到的直线则代表这个正方形也能看到;

投影有3种情况:

线段完全不想交的两种情况:  

-----------------------线段1                                             |               ------------------线段2

                                      ----------------------- 线段2      |                                                  -------------------线段1

这种情况下显然后放入的正方形对先前的那一个完全没有影响

线段覆盖的两种情况:

   ------------------------------- 线段1                               |             -----------------------------线段2

            ------------- 线段2                                            |                   -----------------线段1

如果是上面的情况,那么几乎可以确定新加入的正方形看不到
如果是下面的情况,那么几乎可以确定已存在的正方形看不到

普通情况:

------------------线段1                                                  |            -------------------------线段2

            --------|--------|线段2                                       |                            ------------|-----------|线段1

                      |--------|投影线段                                 |                                            |-----------|线段投影        

于是新来的线段相当于被砍掉一部分.                                                                         

 

View Code
#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<algorithm>

#include<cmath>

#include<queue>

#include<set>

#include<map>

#include<cstring>

#include<vector>

using namespace std;

class Square

{

public:

      int len,left,right;    

}square[54];

int Max( int a, int b )

{

   return a > b ? a : b;    

}

int main(  )

{

    int n,left;

    while( scanf( "%d",&n ),n )

    {

       for( int i = 0 ; i < n ; i++ )

       {

            scanf( "%d",&square[i].len );

            square[i].left = 0;

            for( int j = 0; j < i ; j ++ )//求最左边的点 

            {

                square[i].left = Max( square[i].left , square[j].right - abs( square[i].len - square[j].len ));    

            }        

            square[i].right = square[i].left + square[i].len * 2;

       }

       for( int i = 1 ; i < n ; i ++ )

       {

               for( int j = 0; j < i ; j ++ )

               {

                if( square[i].left < square[i].right )

                {//如果是新加入的S边大于原来的S,并且新加入的S最左边小于原来的最右边;

                //则会存在投影覆盖 

                    if( square[i].len > square[j].len && square[i].left < square[j].right )

                        square[j].right = square[i].left;

                //如果是新加入的S边小于原来的S,并且新加入的S最左边小于原来的最右边;

                //则会存在投影覆盖

                    if( square[i].len < square[j].len && square[j].right > square[i].left )

                        square[i].left = square[j].right;

                }         

            }

       }

       for( int i = 0; i < n ; i ++ )

       {

          if( square[i].left < square[i].right )

              printf( "%d ",i+1 );        

       }

       puts( "" );

    }

    //system( "pause" );

    return 0;

}

 

你可能感兴趣的:(poj)