题意:不断加45°角站立的正方形,在互不相交的情况下,使得每个正方形底端点尽量靠左,求在上方视角可以看到的正方形编号
解法:
先求每个正方形左右端点
L[i] R[i] X[i] 分别表示 i正方形的左端点、右端点、边长
因为每个新正方形 i 总会和另外一个正方形 j 的一条边重合,由此可计算新正方形左端点坐标L= R[j]-fabs(X[i]-X[j])/sqrt(2)
每加一个正方形,和之前所有正方形枚举计算出L 取所有L中的最大值,是合法情况 且 是最优解
其次求
每个正方形左右有效端点(上方可见范围)
更新每个正方形之间的覆盖影响
i 正方形 对前面 j 正方形的影响:
1.若X[j]<X[i] 则 j 正方形 在 i 正方形下方 , 更新 j 正方形有效端点
2.若X[j]>X[i] 则 j 正方形 在 i 正方形上方,更新 i 正方形有效端点
更新完后,若 i 正方形 可见范围 >0 ,则可见,输出
#include <map> #include <set> #include <cmath> #include <math.h> #include <queue> #include <cstdio> #include <vector> #include <climits> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #define down DOWN using namespace std; double X[55]; double L[55],R[55]; double g=sqrt(double(2)); int main() { int n; while(~scanf("%d",&n)&&n) { memset(vis,0,sizeof(vis)) ; double mx=0; int mxi=-1; for(int i=0;i<n;i++) { scanf("%lf",&X[i]); } for(int i=0;i<n;i++) { double l=0; for(int j=0;j<i;j++) { l=max(l,R[j]-fabs(X[i]-X[j])/g); } L[i]=l; R[i]=l+X[i]*g; } int flag=0; for(int i=0;i<n;i++) { for(int j=0;j<i;j++) { if(X[j]<X[i]&&L[i]<R[j]) { R[j]=L[i]; } if(X[i]<X[j]&&R[j]>L[i]) { L[i]=R[j]; } } } for(int i=0;i<n;i++) { if(R[i]-L[i]>1e-10) { if(flag==0) { flag=1; printf("%d",i+1); } else printf(" %d",i+1); } } printf("\n"); } }
Kadj Squares 几何思维
最新推荐文章于 2020-10-08 16:06:08 发布