poj3347 Kadj Squares (計算幾何)

D - Kadj Squares
Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u
Submit Status

Description

In this problem, you are given a sequence S1S2, ..., Sn of squares of different sizes. The sides of the squares are integer numbers. We locate the squares on the positive x-y quarter of the plane, such that their sides make 45 degrees with x and y axes, and one of their vertices are on y=0 line. Let bi be the x coordinates of the bottom vertex of Si. First, put S1 such that its left vertex lies on x=0. Then, put S1, (i > 1) at minimum bi such that

  • bi > bi-1 and
  • the interior of Si does not have intersection with the interior of S1...Si-1.

 

 

The goal is to find which squares are visible, either entirely or partially, when viewed from above. In the example above, the squares S1S2, andS4 have this property. More formally, Si is visible from above if it contains a point p, such that no square other than Si intersect the vertical half-line drawn from p upwards.

Input

The input consists of multiple test cases. The first line of each test case is n (1 ≤ n ≤ 50), the number of squares. The second line contains nintegers between 1 to 30, where the ith number is the length of the sides of Si. The input is terminated by a line containing a zero number.

Output

For each test case, output a single line containing the index of the visible squares in the input sequence, in ascending order, separated by blank characters.

Sample Input

4
3 5 1 4
3
2 1 2
0

Sample Output

1 2 4
1 3

題意:變長不同的n個正方形,斜45度按順序平放在座標軸上,儘量靠左但不能躍出x=0,

   問從上往下看,哪些正方形是可見的。

題解:1、假如前i-1個正方形位置都確定了,那麼可以讓第i個正方形與前i-1個正方形每個

   都計算一次它如果和它相依靠的話左邊座標的值,然後取一個最大的便是這個正方形

   的左端點位置。

   2、對於j<i的正方形,如果i的邊長大於j那麼j的最右能看到的部分就不會比i的最左端

   點大,反之,i的最左能看到的部分就不會比j最右端點小。

   3、通過第2步篩選,將那些最左能看到的端點比最右能看到端點大或等於的去掉,剩

   下的就是所要求的。

注意:爲避免浮點數運算,根號2約掉了,代碼中的邊長實際上指的就是邊長/根號2,也可以

   將該題理解爲將正方形投影到x軸上。

#include <iostream>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;
struct sa
{
    int l,r,len;
}data[55];
int main()
{
    int n;
    while(cin>>n&&n)
    {
        memset(data,0,sizeof(data));
        for(int i=0;i<n;i++)
        {
            cin>>data[i].len;
            for(int j=0;j<i;j++)
            data[i].l=max(data[i].l,data[j].r-abs(data[i].len-data[j].len));//求左端點,根據等腰直角三角形的性質可推出關係
            data[i].r=data[i].l+2*data[i].len;
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<i;j++)
            {
                if(data[j].r>data[i].l)//可更新
                {
                    if(data[j].len<data[i].len)
                    data[j].r=data[i].l;//右面的把左面的擋住了一塊
                    else 
                    data[i].l=data[j].r;//左面的把右面的擋住了一塊
                }
            }
        }
        for(int i=0;i<n;i++)
        {
            if(data[i].l<data[i].r)
                cout<<i+1<<" ";
        }
        cout<<endl;
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章