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

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

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

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

View Code
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 using namespace std;
 6 struct data
 7 {
 8     double len,left,right;
 9 }po[60];
10 const double q2=sqrt(2.0),eps=1e-4;
11 int main()
12 {
13     int n;
14     while(scanf("%d",&n),n)
15     {
16         for(int i=1;i<=n;i++)
17             scanf("%lf",&po[i].len);
18         for(int i=1;i<=n;i++)
19         {
20             double left=0;
21             for(int j=1;j<i;j++)
22                 left=max(left,po[j].right-fabs(po[i].len-po[j].len)/q2);
23             po[i].left=left;
24             po[i].right=left+po[i].len*q2;
25         }
26         for(int i=1;i<=n;i++)
27         {
28             for(int j=1;j<i;j++)
29             {
30                 if(po[i].len>po[j].len&&po[i].left<po[j].right)
31                     po[j].right=po[i].left;
32                 if(po[i].len<po[j].len&&po[j].right>po[i].left)
33                     po[i].left=po[j].right;
34             }
35         }
36         bool first=true;
37         for(int i=1;i<=n;i++)
38         {
39             if(po[i].left<po[i].right-eps)
40             {
41                 if(first)
42                     first=false;
43                 else
44                     printf(" ");
45                 printf("%d",i);
46             }
47         }
48         printf("\n");
49     }
50     return 0;
51 }