http://codeforces.com/gym/101047/problem/K
题目:给定n<=2000条绳子,要你找出其中三条,围成三角形,并且要使得围成的三角形面积最小
思路: 考虑一下三角形面积公式1/2a*b*sinO ,那么可以暴力枚举两条边,第三条边要尽量小,为什么呢?因为我要使得O角尽量小。sin值也小了。这是根据小边对小角得到的。所以要找到第一条>a-b的。这样就能使结果最优。这个找可以用二分啦。同理找一个<a+b的
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> const int maxn = 2e3+20; double a[maxn]; const double eps = 1e-6; bool same(double a,double b) { return fabs(a-b)<eps; } double S(double a,double b,double c) { double q = (a+b+c)/2; return sqrt(q*(q-a)*(q-b)*(q-c)); } bool check (double a,double b,double c) { if (a-b>=c) return false; if (a-c>=b) return false; if (b-c>=a) return false; return true; } void work () { int n; scanf("%d",&n); for (int i=1;i<=n;++i) scanf("%lf",&a[i]); const double gg=-1; double ans = gg; sort(a+1,a+1+n); for (int i=2;i<=n-1;++i) { for (int j=i+1;j<=n;++j) { double find = a[j]-a[i]; int pos = upper_bound(a+1,a+1+n,find)-a; if (pos!=n+1&&pos!=j&&pos!=i&&check(a[i],a[j],a[pos])) { if (ans==-1) ans=S(a[i],a[j],a[pos]); else ans=min(ans,S(a[i],a[j],a[pos])); } find=a[j]+a[i]; pos = lower_bound(a+1,a+1+n,find)-a; if (pos!=n+1&&pos-1!=j&&pos-1!=i&&check(a[i],a[j],a[pos-1])) { if (ans==-1) ans=S(a[i],a[j],a[pos-1]); else ans=min(ans,S(a[i],a[j],a[pos-1])); } } } if (same(ans,gg)) { printf ("-1\n"); return ; } printf ("%0.10f\n",ans); return ; } int main() { #ifdef local freopen("data.txt","r",stdin); #endif int t; scanf("%d",&t); while(t--) work(); return 0; }
Gym 101047K Training with Phuket's larvae
时间: 2024-10-10 04:04:26