题意:变长不同的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 }