UVA 11186 - Circum Triangle(圆上三角形求法)

博客讲述了作者在解决UVA 11186 - Circum Triangle问题时遇到的超时问题,通过不断优化最终AC的经历。文章详细分析了一种聪明的解题思路,涉及到利用三角形面积公式计算夹角的和差,并解释了公式 `(n + 2i - 2j) * sin(c) / 2` 的来源。作者还分享了自己的原始代码以及优化后的代码实现。
摘要由CSDN通过智能技术生成

这个题 感觉数据是500 就直接三层循环上去了。 。但是超时了。 我用了最简单的方法 可能是运算量略大的原因吧。(好吧。          在自己稍微优化之后A了。 跑了2.059秒,代码在最后面)


在不会优化的情况下。 去网上搜了题解。 


第一份代码。 在我看明白之后  不得不佩服 原作者的聪明机智。 也算是 学到了。

先上代码后讲解。  


#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <cctype>
using namespace std;
#define ll long long
typedef unsigned long long ull;
#define maxn 1001
#define INF 1<<30
double p = acos(-1);
struct po{
    double x,y;
} s[maxn];
int main (){
    int n;
    double r;
    while(scanf("%d%lf",&n,&r) != EOF && n && r) {
        double f[maxn];
        for(int i = 0; i < n; i++){
            scanf("%lf",&f[i]);
            f[i] = f[i]/180.0*p;

        }
        sort(f,f+n);
        double sum = 0;
        for(int i = 0; i < n-1; i++){
            for(int j = i+1; j < n; j++){
                sum += (n + 2*i - 2*j)*sin(f[j] - f[i]);
            }
        }
        sum = sum * r * r / 2;
        sum = floor(sum+0.5);
        printf("%lld\n",(ll)sum);
    }
    return 0;
}


在这个代码中。 大体思路是很清晰的。 就是找出 每个点 所与x正半轴的夹角。 然后 在sum中  sin(f【j】 - f【i】) 与后面 sum * r*r /2  


便可以知道  用的是  a*b*sin(c)/ 2  这个公式。  但是前面 的 (n+2*i- 2*j) 似乎很难理解。


自己没有看出来。 找了川神 他看了一会给我讲解的。




在上图中。 我们假定要求 S(i,j,k) 如果k在 j的左侧  那么 S(i,j,k) = S(i,k,o)+s(i,j,o) - s(k,i,o); 显然 只要k在j的左侧  s(i,j,0) 在用来求 做和用的。

如果k在 j的右侧  那么 S(i,j,k) = S(i,k,o)+s(i,j,o) - s(k,j,o); 显然 只要k在j的右侧  s(i,j,0) 在用来求 做和用的。

如果k在 i,j的中间  那么 S(i,j,k) = S(j,k,o)+s(i,k,o) - s(i,j,o); 显然 只要k在i,j的中间  s(i,j,0) 在用来求 做差用的。

那么 我们就可以对于 线段 i,j  对于后面 或者前面的点来说 都需要加上oji 这一块面积  而对于  ij 中间的 点来说  都需要 减去这一块。

那么对于这一块面积。  总共的 需求为   当k在左侧的时候 : n - j - 1    k在右侧是时候   为  i   加起来为  n - j + i - 1;

对于k位于中间来说。   总共需要减去 个数为   j - i  - 1个。

那么 总共就是  n + 2i - 2j  个。  乘上  这一块的面积 sin(c)  就OK了


上面的公式也就推出来了。 


下面是自己写的那个代码。。  最简单了。


#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <cctype>
using namespace std;
#define ll long long
typedef unsigned long long ull;
#define maxn 1001
#define INF 1<<30
double p = acos(-1);
struct po{
    double x,y;
};
po s[maxn];
double l[maxn][maxn];
double ss;
double line(int i,int j){
    return sqrt((s[i].x - s[j].x) * (s[i].x - s[j].x) + (s[i].y - s[j].y) * (s[i].y - s[j].y));
}
int main (){
    int n;
    double r;double jiao;
    while(scanf("%d%lf",&n,&r) != EOF && n && r){
        for(int i = 0; i < n; i++){
            scanf("%lf",&jiao);
            jiao = jiao/180*p;
            s[i].x = r * cos(jiao);
            s[i].y = r * sin(jiao);
        }
        for(int i = 0; i < n-1; i++){
            for(int j = 0; j < n; j++){
                l[i][j] = line(i,j);
                l[j][i] = l[i][j];
            }
        }
        double sum = 0;
        for(int i = 0; i < n-2; i++){
            for(int j = i+1; j < n-1; j++){
                for(int k = j+1; k < n; k++){
                    ss = (l[i][j]+l[i][k]+l[j][k])/2.0;
                    sum += sqrt(ss*(ss-l[i][j])*(ss-l[i][k])*(ss-l[j][k]));
                }
            }
        }
        printf("%.0lf\n",sum);
    }
    return 0;
}



评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值