• <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

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

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

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

            //三點(diǎn)是否共線
            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);
            }

            //點(diǎn)nOne和點(diǎn)nTwo是否在直線(nBeg,nEnd)的同一側(cè)(不能在直線上)
            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的坐標(biāo)代入直線方程計(jì)算結(jié)果,然后將結(jié)果相乘
                
            //乘積必須大于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("點(diǎn):%d,點(diǎn):%d,在直線nBeg:%d, nEnd:%d的同一側(cè)\n", nOne, nTwo, nBeg, nEnd);
                }
                return nRes > 0;
            }

            //點(diǎn)是否在三角形(nOne, nTwo, nThree)外部
            bool PointOutTriangle(int nOne, int nTwo, int nThree, int nPoint)
            {
                //前面3個(gè)ifelse是判斷點(diǎn)是否在邊上
                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)的外側(cè)也會(huì)判斷為假
                
            //所以需要先在上面判斷點(diǎn)是否在邊的內(nèi)側(cè)
                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("點(diǎn):%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("點(diǎn):%d, 在三角形:%d,%d,%d內(nèi)部\n", i, nOne, nTwo, nThree);
                        return false;
                    }
                }
                
                return true;
            }

            //計(jì)算三角形(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 閱讀(1284) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 數(shù)學(xué)題

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

            導(dǎo)航

            統(tǒng)計(jì)

            公告

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            me

            好友

            同學(xué)

            網(wǎng)友

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            久久香综合精品久久伊人| 综合久久国产九一剧情麻豆| 午夜精品久久久久久99热| 一本色道久久88—综合亚洲精品| 久久国产色av免费看| 亚洲AV无码久久精品成人| 久久99国产精品久久99果冻传媒| 久久人人爽人人爽AV片| 亚洲精品乱码久久久久66| 久久亚洲国产欧洲精品一| 精品久久人人爽天天玩人人妻| 91麻豆国产精品91久久久| 国产精品一久久香蕉产线看| 久久人妻少妇嫩草AV蜜桃| 99久久这里只有精品| 亚洲精品NV久久久久久久久久| 2022年国产精品久久久久| 亚洲国产精品成人AV无码久久综合影院 | 久久伊人五月天论坛| 久久免费视频1| 久久天天躁狠狠躁夜夜不卡| 国产精品99久久精品| 亚洲国产另类久久久精品黑人 | 亚洲人成网站999久久久综合| 久久精品国产精品亚洲毛片| 偷偷做久久久久网站| 99久久精品无码一区二区毛片 | 久久精品麻豆日日躁夜夜躁| 怡红院日本一道日本久久| 欧美丰满熟妇BBB久久久| 亚洲欧美日韩精品久久亚洲区| 91精品国产综合久久香蕉| 69SEX久久精品国产麻豆| 久久久久99精品成人片试看| 97精品依人久久久大香线蕉97| 午夜精品久久久久久影视777| 久久强奷乱码老熟女| 性做久久久久久免费观看| 久久综合鬼色88久久精品综合自在自线噜噜| 亚洲欧美精品伊人久久| 久久精品99无色码中文字幕|