• 三角形



    【 问题描述 】
     平面上有N条直线,用方程A i x + B i y +C i
    =0表示。这些直线没有三线共点的。现在
    要你计算出用这些直线可以构造出多少三
    角形?
    【 输入格式 】
     第1行:一个整数N(1 ≤ N≤ 300000)。
     下面N行:每行3个整数:Ai, Bi 和Ci,
    表示对应直线方程的系数。不超过10^9.



    【 数据规模与约定 】
    对于40%的数据,N ≤1000;

    对于100%的数据,N≤300000。

    题解:考试的时候想打个暴力,应该能得30分,但只得了15分,后来发现多判断了y2与y3是否相交,若只是这样,还不会出错,但是判断的时候误写成了A1*B2-B1*B2!=0,追悔莫及,画蛇添足,还添错了。先找出两两相交的直线,然后从1到n枚举每条直线y1,枚举与它相交的直线y2,再枚举与y2相交的直线y3,根据相交直线的公式A1*B2-B1*A2!=0来判断y3是否与y1相交,若满足,则说明三条直线能围成一个三角形.

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    #define N 5010
    using namespace std;
    int n;
    ll ans=0;
    int f[N][N],num[N]={0};
    struct node
    {
        int a,b,c;
    }fc[N];
    int main()
    {
        freopen("trokuti.in","r",stdin);
        freopen("trokuti.out","w",stdout);
        
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
          scanf("%d%d%d",&fc[i].a,&fc[i].b,&fc[i].c);
        for (int i=1;i<=n-1;i++)
          for (int j=i+1;j<=n;j++)
             if ((fc[i].a*fc[j].b-fc[i].b*fc[j].a)!=0) f[i][++num[i]]=j; 
        for (int i=1;i<n;i++)
          for (int j=1;j<=num[i];j++)
            {
                int x=f[i][j];
                int y=num[x];
                for (int k=1;k<=y;k++)
                  {
                       int kk=f[x][k];
                       if ((fc[i].a*fc[kk].b-fc[i].b*fc[kk].a)!=0) ans++; 
                  }
                 
            }
        cout<<ans<<endl;
          
        fclose(stdin);
        fclose(stdout);
        
        return 0;                                                      
    }
    30

    正解:由于任意三条互不平行且非三线共点的直线均能围成一个切仅一个三角形。而题目中说不存在三线共点的情况,所以只需统计出所有直线组合中三线都互不平行的数量即可。判断是否相交时,可用斜率进行判断,统计斜率不同的直线y的数量,并统计出与y平行的直线的数量(即与y斜率相同的直线)。

     然后用计算出n条直线中取出3条直线有多少种不同的方案数。然后减去平行直线的组合方案数(包含三条直线中有两条直线平行,三条直线均互相平行)。即为最终答案。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<map>
    #define M 300000
    #define ll long long
    const int N=-1e9;
    using namespace std;
    int n,num=0;
    ll ans;
    double a[M];
    map<double,int>f;//用map映射,妈妈再也不用担心会爆炸啦。 
    ll c(int x,int y)//从x中取出y个数的不同的方案数 
    {
        ll kk=1;
        if (x<y) return 0;
        for (int i=x;i>=x-y+1;i--) kk*=i;
        for (int i=1;i<=y;i++) kk/=i;
        return kk; 
    }
    int main()
    {
        freopen("trokuti.in","r",stdin);
        freopen("trokuti.out","w",stdout);
        scanf("%d",&n);
        for (int i=1,A,B,C;i<=n;i++)
          {
               scanf("%d%d%d",&A,&B,&C);
               if (B==0)
                 f[N]++;//由于斜率可能不存在,因此用负无穷来储存这一情况 
               else
                 {
                    double k=(double(A)/B)*1.0;
                  if (!f[k]) a[++num]=k;
                  f[k]++;     
               }
          }
        if (f[N]) a[++num]=N;
        ans=c(n,3); 
        for (int i=1;i<=num;i++)
          {
               int k=f[a[i]];
               ans-=c(k,3);//三条直线均互相平行的可能 
               ans-=c(k,2)*(n-k);//三条直线中两条直线互相平行的可能 
          }
        cout<<ans<<endl;
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    100
  • 相关阅读:
    搭建个人Spring-Initializr服务器
    “不蒜子”统计总访问人数脚本
    基于Hazelcast及Kafka实现的分布式锁与集群负载均衡
    虚拟机部署hadoop集群
    程序员、黑客及开发者之间的区别
    今日校园自动登录教程
    逆向DES算法
    来自穷逼对HttpCanary的蹂躏
    今日校园提交签到和查寝-Java实现
    JS 判断数据类型方法
  • 原文地址:https://www.cnblogs.com/sjymj/p/5998116.html
Copyright © 2020-2023  润新知