最優三角剖分

問題描述:ios

  給一個有n個頂點的凸多邊形,有不少方法進行三角剖分(polygon triangulation) 。給每一個三角形規定一個權函數w(i,j,k)(好比三角形的周長或者三頂點的權和或者三角形的面積等等),求讓全部三角形權和最大的方案。函數

 

分析:spa

  這個問題的關鍵在於狀態的定義,由於若是容許隨意切割,顯然任意「半成品」 多邊形的各個頂點能夠是原多邊形中隨意選取的,很難簡潔的定義成狀態。但咱們又能夠發現,對於同一種切割方法,咱們能夠有多種切割順序,但切割方法就已經決定了這個方法產生的結果,咱們只要計算其中一種切割順序就行了,因此不如把決策順序規範化。.net

  定義 d[i,j] 爲從頂點 i 開始到頂點 j 所構成的多邊形的最大三角剖分權和,則邊 i→j 在此多邊形內必定剛好屬於一個三角形 i→j→k ,因此多邊形就被分紅了三部分:▲ikj 及其左右兩部分子多邊形。這個切割方法保證了兩個子多邊形它們的頂點編號是連續的。因此咱們只須要每次將表明這個多邊形的兩個頂點(始、末)做爲分割後的其中一個三角形的一條邊,而後枚舉第三個頂點 k 的狀況,再依次分割下去直到分割完成。code

  因此,有狀態轉移方程:d[i,j] = max{d[i,k]+d[k,j]+w(i,j,k)},時間複雜度爲O(n3)blog

 

 

 

 


 

結合一道具體的題目來加深一下理解ci

題目連接:get

  https://cn.vjudge.net/problem/UVA-1331博客

題意:string

  給定一個n邊形,要你求將這個n邊形分割成若干三角形後,其中面積最大的三角形的最小值

分析:

  典型的最優三角剖分問題,狀態轉移方程:d[i][j] = min{max{SΔijk,d[i][k],d[k][j]}} (i<k<j)

  不過這裏須要注意的是,這道題並無指明這個多邊形的凹凸性,因此對於凹多邊形的狀況,須要加上一個判斷,即判斷Δijk是不是合法的三角形,若是Δijk內部含有多邊形的一個頂點,那麼就是不合法的

  具體分析細節,這篇博客寫的不錯https://blog.csdn.net/c20190102/article/details/75418824

代碼:

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<cstring>
 4 #include<cmath>
 5 using namespace std;
 6 const int maxn = 60;
 7 const int INF = 0x3f3f3f3f;
 8 int x[maxn], y[maxn];
 9 double dp[maxn][maxn];
10 int n;
11 double area(int a, int b, int c)
12 {
13     double ans;
14     ans = (x[a] * y[b] + x[b] * y[c] + x[c] * y[a] - x[a] * y[c] - x[b] * y[a] - x[c] * y[b]) * 1.0 / 2;
15     return abs(ans);
16 }
17 
18 int judge(int i, int j, int k)
19 {
20     for(int v = 0; v < n; v++)
21     {
22         if(v == i || v == j || v == k)
23             continue;
24         else
25         {
26             double sum = area(i, j, v) + area(i, k, v) + area(j, k, v);
27             if(abs(sum - area(i, j, k)) <= 0.001)    //由於有浮點數偏差,這裏初略認爲小於0.001即爲相等
28                 return 0;
29         }
30     }
31     return 1;
32 }
33 int main()
34 {
35     int t;
36     cin >> t;
37     while(t--)
38     {
39         memset(dp, 0, sizeof(dp));
40         cin >> n;
41         for(int i = 0; i < n; i++)
42         {
43             cin >> x[i] >> y[i];
44         }
45         //i<k<j    注意邊界
46         for(int i = n - 3; i >= 0; i--)
47         {
48             for(int j = i + 2; j <= n - 1; j++)
49             {
50                 dp[i][j] = INF;
51                 for(int k = i + 1; k < j; k++)
52                 {
53                     if(judge(i, j, k))
54                         dp[i][j] = min(dp[i][j], max(area(i, j, k), max(dp[i][k], dp[k][j])));
55                 }
56             }
57         }
58         printf("%.1lf\n", dp[0][n - 1]);
59     }
60     return 0;
61 }
相關文章
相關標籤/搜索