• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            uva 10112 - Myacm Triangles

               這是一個幾何題。題意是給出一系列點,點最多才15個,求一個這里面的三個點組合出來的三角形,其面積是最大的,而且沒有任何其它
            的點在這個三角形的內部和邊界上。求三角形的面積,題目上面已經給了公式,也可以用0.5*|a|*|b|*sin(a,b)求,這里的a和b指的是2條
            邊代表的向量。
               現在就剩下一個問題了,怎么判斷一個點在三角形的內部和邊界上。在邊界上,比較好判斷,判斷是否共線,然后再點是在線段的內部。
            具體說明下,判斷一個點在三角形內部的思路。我用的還是線性規劃的思想。如果該點在三角形的內部,那么任取三角形的一條邊,
            該內部點和剩余的三角形的一個頂點必定在三角形的那條的邊的同一側。
            這個方法也可以推廣到N邊的凸多邊形,證明的話很簡單,
            因為線性規劃一直在劃分區域。所以,劃分到最后圍起來的區域就是凸多邊形的內部了。
               至于寫代碼的話,由于是第一次寫這種幾何題,寫得很凌亂。

               代碼如下:
            #include <stdio.h>
            #include <math.h>

            #define MAX (20)
            int nN;
            struct Point
            {
                char szLabel[5];
                int x;
                int y;
            };
            Point points[MAX];

            //三點是否共線
            bool IsOneLine(int nOne, int nTwo, int nThree)
            {
                int nA = points[nTwo].x - points[nOne].x;
                int nB = points[nTwo].y - points[nOne].y;
                int nC = points[nThree].x - points[nOne].x;
                int nD = points[nThree].y - points[nOne].y;
                
                return (nA * nD == nB * nC);
            }

            //點nOne和點nTwo是否在直線(nBeg,nEnd)的同一側(不能在直線上)
            bool IsSameSide(int nBeg, int nEnd, int nOne, int nTwo)
            {
                //求直線的向量
                int nA = points[nBeg].x - points[nEnd].x;
                int nB = points[nBeg].y - points[nEnd].y;
                
                //直線方程為nB(x - points[nBeg].x) - nA(y - points[nBeg].y) = 0
                
            //分別用nOne和nTwo的坐標代入直線方程計算結果,然后將結果相乘
                
            //乘積必須大于0
                int nRes = (nB * (points[nOne].x - points[nBeg].x) - nA * (points[nOne].y - points[nBeg].y))
                * (nB * (points[nTwo].x - points[nBeg].x) - nA * (points[nTwo].y - points[nBeg].y));
                
                if (nRes > 0)
                {
                    //printf("點:%d,點:%d,在直線nBeg:%d, nEnd:%d的同一側\n", nOne, nTwo, nBeg, nEnd);
                }
                return nRes > 0;
            }

            //點是否在三角形(nOne, nTwo, nThree)外部
            bool PointOutTriangle(int nOne, int nTwo, int nThree, int nPoint)
            {
                //前面3個ifelse是判斷點是否在邊上
                if (IsOneLine(nOne, nTwo, nPoint))
                {
                    if ((points[nOne].x - points[nPoint].x) * (points[nTwo].x - points[nPoint].x) <= 0)
                    {
                        return false;
                    }
                }
                else if (IsOneLine(nOne, nThree, nPoint))
                {
                    if ((points[nOne].x - points[nPoint].x) * (points[nThree].x - points[nPoint].x) <= 0)
                    {
                        return false;
                    }
                }
                else if (IsOneLine(nTwo, nThree, nPoint))
                {
                    if ((points[nTwo].x - points[nPoint].x) * (points[nThree].x - points[nPoint].x) <= 0)
                    {
                        return false;
                    }
                }
                
                //下面的IsSameSide如果nPoint在直線的(nOne,nTwo)的外側也會判斷為假
                
            //所以需要先在上面判斷點是否在邊的內側
                return !(IsSameSide(nOne, nTwo, nThree, nPoint)
                && IsSameSide(nOne, nThree, nTwo, nPoint)
                && IsSameSide(nTwo, nThree, nOne, nPoint));
            }

            bool IsValid(int nOne, int nTwo, int nThree)
            {
                if (IsOneLine(nOne, nTwo, nThree))
                {
                    //printf("點:%d,%d,%d共線\n", nOne, nTwo, nThree);
                    return false;
                }
                
                for (int i = 0; i < nN; ++i)
                {
                    if (i == nOne || i == nTwo || i == nThree)
                    {
                        continue;
                    }

                    if (!PointOutTriangle(nOne, nTwo, nThree, i))
                    {
                        //printf("點:%d, 在三角形:%d,%d,%d內部\n", i, nOne, nTwo, nThree);
                        return false;
                    }
                }
                
                return true;
            }

            //計算三角形(nOne, nTwo, nThree)的面積
            double GetArea(int nOne, int nTwo, int nThree)
            {
                return 0.5 * fabs((points[nThree].y - points[nOne].y) * (points[nTwo].x - points[nOne].x)
                - (points[nTwo].y - points[nOne].y) * (points[nThree].x - points[nOne].x));
            }

            int main()
            {
                while (scanf("%d", &nN), nN)
                {
                    for (int i = 0; i < nN; ++i)
                    {
                        scanf("%s%d%d", points[i].szLabel, &points[i].x, &points[i].y);
                    }
                    
                    double fMaxArea = 0.0;
                    int nI = -1, nJ = -1, nK = -1;
                    for (int i = 0; i < nN - 2; ++i)
                    {
                        for (int j = i + 1; j < nN - 1; ++j)
                        {
                            for (int k = j + 1; k < nN; ++k)
                            {
                                if (IsValid(i, j, k))
                                {
                                    //printf("i:%d,j:%d,k:%d valid\n", i, j, k);
                                    double fArea = GetArea(i, j, k);
                                    //printf("Area:%f\n", fArea);
                                    if (fArea > fMaxArea)
                                    {
                                        nI = i;
                                        nJ = j;
                                        nK = k;
                                        fMaxArea = fArea;
                                    }
                                }
                            }
                        }
                    }
                    printf("%s%s%s\n", points[nI].szLabel, points[nJ].szLabel, points[nK].szLabel);
                }
                
                return 0;
            }

            posted on 2012-05-07 14:07 yx 閱讀(1278) 評論(0)  編輯 收藏 引用 所屬分類: 數學題

            <2012年3月>
            26272829123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            導航

            統計

            公告

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            me

            好友

            同學

            網友

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            久久亚洲2019中文字幕| 久久99国产精品尤物| 久久99国产精品久久久 | 国产A三级久久精品| 久久精品国产WWW456C0M| 丰满少妇人妻久久久久久4| 国产日产久久高清欧美一区| 久久综合给久久狠狠97色| 精品久久久无码人妻中文字幕豆芽 | 久久亚洲精品无码aⅴ大香| 亚洲美日韩Av中文字幕无码久久久妻妇 | 香蕉久久夜色精品升级完成| 亚洲精品美女久久久久99| 无码国内精品久久人妻| 精品无码久久久久久午夜| 精品国产91久久久久久久| 青青青伊人色综合久久| 久久久久久久综合日本| 97久久婷婷五月综合色d啪蜜芽| 99精品国产99久久久久久97| AV狠狠色丁香婷婷综合久久| 久久中文娱乐网| 国内精品久久久久影院老司| 国内精品九九久久久精品| 国产精品99久久精品爆乳| 久久伊人精品一区二区三区 | 97久久精品人妻人人搡人人玩| 久久久久久久99精品免费观看| 理论片午午伦夜理片久久 | 久久夜色精品国产亚洲av| 2021最新久久久视精品爱| 久久99精品国产| 热久久最新网站获取| 狠狠久久亚洲欧美专区| 亚洲精品无码久久不卡| 国产一级做a爰片久久毛片| 国内精品伊人久久久影院| 久久精品亚洲福利| 久久国产精品一国产精品金尊| 久久无码精品一区二区三区| 久久精品国产亚洲AV无码娇色|