日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

写到usaco上的一题可能题解是凸包所以转来这篇文章看看

發布時間:2023/11/27 生活经验 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 写到usaco上的一题可能题解是凸包所以转来这篇文章看看 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?

凸包 graham 算法

標簽:?算法distancexpstructoutputinput ?8371人閱讀?評論(2)?收藏?舉報 ?分類: ??

向量:

1.向量的內積(數量積,點乘):

公式:a· b = |a| * |b| cos<a, b>a.x* b.y + b.x * a.y


2.向量的外積(向量積,差乘):

公式|c|= |a|*|b|*sin<a, b> = a.x * b.y - b.x * a.y

意義:

1).兩個向量和坐標原點所圍成的面積(可正可負)。

2).值為正值表示向量a在向量b的順時針方向,反之,向量a在向量b的逆時針方向,相等時,共線.

凸包:由平面上的最小點所圍成的多邊形,平面上任何其它的點都在這個多邊形內部,這個多邊形就稱為

凸包。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? (圖1)?


graham算法:

第一步:選取x軸坐標最小的點,如果存在多個選y軸坐標最小的點.(如圖1,p0)


第二步:排序.從下到上掃描有其它點.(如圖1)掃描的結果順序,p0, p4, p5, p7,?p9,p6, p8, p2,p3, p1.


數學公式向量的外積模公式:|c|(是模不是絕對值符號)= |a|*|b|*sin<a, b> = a.x * b.y – b.x * a.y

|c|> 0:向量a在向量b的順時針方向,因為此例原點坐標取x軸坐標最小的點,所以,向量a在向

b的下方.(p0-p4線段在p0-p5的下方).

|c|= 0:共線時,按照與原點距離由小到大的順序.



第三步:按照第二步得到的頂點順序進行graham掃描.按照本例選取的原點方式,當掃描到左拐(p0,p4, p5)時保留(p4),右拐(p9,p6, p8)時刪除頂點(p6),結果就是凸包的頂點集.(綠線掃描的順序,紅線為左拐點).共線時,刪除距離較小的點.

注意:右拐刪除結點時,必須回溯與前面保留的點重新比較,因為刪除一個點后先前拐點性質會發生變化

例如:刪除p6,(p7, p9, p8)?也是右拐了.

所謂的左拐/右拐就沿著邊界掃描后,其它的點是否在當前點與下一點連線與原點的內部.

例如:結果p7-p8是凸包的頂點,p7-p8直線會把所有其它點擋在原點p0方向的一側.



數學公式:

向量外積模公式

:

p5– p4向量Xp0 – p4?向量>0, (p5–p4)(p0–p4)的順時針方向,左拐

p8– p6向量Xp9 – p6向量<0, (p8–p6)(p9–p6)的逆時針方向,右拐



也可以采用其它向量方式

:

p4p0向量Xp5p0向量>0, (p4p0)(p5p0)的順時針方向,左拐

p6p9向量Xp8p9向量<0, (p6p9)(p8p9)的逆時針方向,右拐



示例程序:

p0:(1, -2)

p1:(1, 2)

p2:(5, 3)

p3:(4,5)

p4:(2, -4)

p5:(6, -6)

p6:(7, 0)

p7:(10, -3)

p8:(9, 4)

p9:(8, -1)



input:

10

1 -2

1 2

5 3

4 5

2 -4

6 -6

7 0

10-3

9 4

8 -1



output:

1 -2

2 -4

6 -6

10-3

9 4

4 5

1 2


源代碼:

#include <iostream>
#include <algorithm>
#include <vector>
#include <fstream>

#define MAX_NUMS 10

typedef struct
{
??? int x;
??? int y;
} veritice;

veritice?? vet[MAX_NUMS];
int?????????????????? n;
std::vector<veritice>? v;

inline int cross(const veritice& p0, const veritice& p1, const veritice& p2)
{
??? veritice u, v;

??? u.x = p1.x - p0.x, u.y = p1.y - p0.y;
??? v.x = p2.x - p0.x, v.y = p2.y - p0.y;

??? return v.x * u.y - u.x * v.y;
}

inline int distance(const veritice& p1, const veritice& p2)
{
??? return (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y);
}

inline int graham_compare(const void* a, const void* b)
{
??? int result = cross(vet[0], *(veritice*)a, *(veritice*)b);

??? if(result)
??????? return result;

??? return distance(vet[0], *(veritice*)a) - distance(vet[0], *(veritice*)b);
}

inline void graham_scan()
{
??? v.push_back(vet[0]);
??? v.push_back(vet[1]);

??? for(int i = 2; i < n; i++)
??? {
??????? while( cross(v[v.size() - 1], v[v.size() - 2], vet[i]) <= 0)
??????????? v.pop_back();

??????? v.push_back(vet[i]);
??? }
}

int main()
{
??? std::ifstream in("case_in");
??? int index = 0;

??? in >> n;

??? for(int i = 0; i < n; i++)
??? {
??????? in >> vet[i].x >> vet[i].y;

??????? if(vet[0].x > vet[i].x || (vet[0].x == vet[i].x && vet[0].y > vet[i].y))
??????????? index = i;
??? }

??? in.close();
// 第一步
??? veritice temp;
??? temp.x?????? = vet[0].x,?????? temp.y?????? = vet[0].y;
??? vet[0].x???? = vet[index].x,?? vet[0].y???? = vet[index].y;
??? vet[index].x = temp.x,???????? vet[index].y = temp.y;

// 第二步
??? qsort(vet + 1, n - 1, sizeof(veritice), graham_compare);

// 第三步
??? graham_scan();

//? 輸出
??? for(unsigned int i = 0; i < v.size(); i++)
??????? std::cout << v[i].x << ' ' << v[i].y << std::endl;

??? return 0;
}

總結

以上是生活随笔為你收集整理的写到usaco上的一题可能题解是凸包所以转来这篇文章看看的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。