题意:
给出两个点的坐标,这两个点分别与原点形成两条射线,这两条射线之间形成一个夹角。给出一些已知边长的正方形,问如何摆放,让正方形与两射线之间围成的面积最大。正方形摆放的角度随意。
思路:
其实玄学的想一下,我们要做的就是让原点和两个交点所确定的三角形尽量大,让正方形在此三角形中的面积尽量小。一减就是答案了。最大的情况就是,三角形的底是所有正方形的对角线之和(最长),对于其确定的三角形来说,因为顶角确定了,所以根据正余弦定理可得,底边越长,高越长。我们设所有正方形边长和为tot,交点A‘(x1,k1x1),B'(x2,k2x2),由横坐标,纵坐标差都为tot可以得到方程组,解出两点坐标。
之后一个问题就是求三角形面积。一开始的想法是硬求,求出A'B'的解析式,点到直线距离算出高,就能求出面积。后来因为涉及到很多次除法,造成了精度损失和爆存储范围。后来想到了可以吧OA'和OB'看成两个向量,根据余弦定理算出三角形的面积,也就是相当于用叉积算出面积之后,减去所有正方形的面积的一半。然后就做出来啦。这个算三角形的方法还是值得一学的。
之后就很好写啦。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <string>
#include <list>
#include <cstdlib>
#include <memory>
#include <cstring>
#include <sstream>
#include <list>
#include <deque>
#include <bitset>
#include <vector>
using namespace std;
#define INF 0x3f3f3f3f
#define PI 3.141592653579
#define FRER() freopen("input.txt" , "r" , stdin);
#define FREW() freopen("output.txt" , "w" , stdout);
#define QIO std::ios::sync_with_stdio(false)
#define mem(a , b) memset(a , b , sizeof(a))
const double eps = 1e-8;
typedef long long ll;
const int maxn = 100+500;
double sqa[maxn];
int main()
{
// FRER();
// FREW();
int n;
while(scanf("%d" , &n) && n)
{
double x1, y1, x2 , y2;
cin >> x1 >> y1 >> x2 >> y2;
double tot = 0;
double k1 = y1/x1 , k2 = y2/x2;
double di = 0 , ssum = 0;
for(int i = 0 ; i < n ; i++)
{
cin >> sqa[i];
tot += sqa[i];
di += sqrt(2)*sqa[i];
ssum += sqa[i]*sqa[i]/2.0;
}
double x3 = tot*(1.0+k1)/(k1-k2);
double y3 = x3 * k1;
double x4 = tot*(1.0+k2)/(k1-k2);
double y4 = x4 * k2;
double ress = fabs(x3*y4 - x4*y3)/2.0;
printf("%.3lf\n" , ress-ssum );
}
return 0;
}