1. 程式人生 > >【動態規劃】UVa 1331 最大面積最小三角形剖分

【動態規劃】UVa 1331 最大面積最小三角形剖分

題目

點選

題目大意

將一個多邊形用它不相交的對角線將它分成若干個三角形,使得最大的三角形面積最小,求最大三角形的面積。如圖是一個六邊形的幾種剖分:

思路

記由點u,u+1,…,v-1,v(u< v)組成的多邊形為F(i,j)

首先,總的多邊形為F(1,N)
對於F(1,N)的一個子多邊形F(i,j)(1<=i<j<=N),可以在點i+1-點j-1中任意找到一個點k,將其分割為:Δijk,F(i,k),F(j,k),如圖:

設d[i][j]表示F(i,j)中的最優解,很顯然,先要找到max{SΔijk,d[i][k],d[k][j]}

SΔijkΔijk的面積),也就是找到以k為分割點,F(i,j)中的最大的三角形的面積,然後列舉k點,使這個最大的三角形面積最小即可。

狀態轉移方程:d[i][j]=min{max{SΔijk,d[i][k],d[k][j]}}(i<k<j)

這樣就完了嗎?不是的,還有一個問題:Δijk合法嗎?例如這樣的“分割”:

k點在如圖位置時,Δijk顯然不合法,因為線段ik不是F(1,7)的對角線!

所以怎麼判斷Δijk是否合法呢?
換個思路,判斷Δijk是否合法實際上就是看Δijk內有沒有其他的點。然後列舉除ijk外每一個點唄,再看這點是不是在Δijk內。

怎麼判斷點是否在Δ

ijk內呢?
“面積法”是很好的辦法:設現在列舉到的點為x,計算T=SΔijx,SΔikx,SΔkjx,再把它們加起來,如果x不在Δijk,顯然T==SΔijk,所以判斷TSΔijk的大小關係即可。不明白的可以畫畫圖,我懶得再畫了……

至於計算面積,我用的海倫公式。

程式碼

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;

#define MAXN 50
#define INF 0x7fffffff
#define eps 0.0001
struct point { double x,y; }p[MAXN+5];//點 int N; double d[MAXN+5][MAXN+5];//動歸 double dis(int x,int y){return sqrt((p[x].x-p[y].x)*(p[x].x-p[y].x)+(p[x].y-p[y].y)*(p[x].y-p[y].y));}//計算兩點距離 double area(int x,int y,int z)//計算由點x,y,z構成的三角形的面積(海倫公式) { double a=dis(x,y),b=dis(y,z),c=dis(x,z); double p=(a+b+c)/2; return sqrt(p*(p-a)*(p-b)*(p-c)); } bool check(int x,int y,int z)//判斷由點x,y,z構成的三角形中有沒有點 { double tarea=area(x,y,z); for(int i=1;i<=N;i++) { if(i==x||i==y||i==z) continue; double a=area(i,x,y),b=area(i,y,z),c=area(i,x,z); if(fabs(a+b+c-tarea)<eps)//double計算有精度誤差,不要用== return 0; } return 1; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&N); for(int i=1;i<=N;i++) scanf("%lf%lf",&p[i].x,&p[i].y); for(int i=N-2;i>=1;i--) for(int j=i+2;j<=N;j++) { d[i][j]=INF; for(int k=i+1;k<j;k++)//選擇分割點 if(check(i,j,k)) d[i][j]=min(d[i][j],max(area(i,j,k),max(d[i][k],d[k][j]))); } printf("%.1lf\n",d[1][N]); memset(d,0,sizeof(d)); } }

相關推薦

動態規劃UVa 1331 大面積三角形

題目 請點選 題目大意 將一個多邊形用它不相交的對角線將它分成若干個三角形,使得最大的三角形面積最小,求最大三角形的面積。如圖是一個六邊形的幾種剖分: 思路 記由點u,u+1,…,v-1,v(u< v)組成的多邊形為F(i,j) 首

Java滾動數組動態規劃UVA - 11137 - Ingenuous Cubrency

得到 lose math scanner light clas details 狀態 ann 滾動數組優化自己畫一下就明白了。 http://blog.csdn.net/u014800748/article/details/45849217 解題思路:本題利用遞推關系解決。

動態規劃長公共子序列問題

clas == 搜索 ios for 參考 pan 公式 是否 題目描述: 給定兩個字符串s1s2……sn和t1t2……tn。求出這兩個字符串最長的公共子序列的長度。字符串s1s2……sn的子序列指可以表示為si1si2……sim(i1<i2<……<im)

動態規劃大正方形 (洛谷 P1387 大正方形)

代碼 log mar 最小 down 思路 計數 -m i++ 輸入格式: 輸入文件第一行為兩個整數n,m(1<=n,m<=100),接下來n行,每行m個數字,用空格隔開,0或1。 輸出格式: 一個整數,最大正方形的邊長。 輸入輸出樣例 輸入樣例: 4 4 0

算法52-----矩陣路徑動態規劃

sum data 列表 路徑 二次 解釋 示例 一行 lse 一、題目:矩陣最小路徑 給定一個包含非負整數的 m x n 網格,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和為最小。 說明:每次只能向下或者向右移動一步。 示例: 輸入: [ [1,3,1],

算法56-----編輯代價動態規劃

狀態 tro 如果 for 字符串 技術 gin 給定 clas 一、題目:最小編輯代價 給定兩個字符串str1和str2,再給定三個整數ic,dc,rc,分別代表插入、刪除、替換一個字符的代價,返回將str1編輯成str2的最小代價。舉例:str1="abc" str

演算法56-----編輯代價動態規劃

一、題目:最小編輯代價 給定兩個字串str1和str2,再給定三個整數ic,dc,rc,分別代表插入、刪除、替換一個字元的代價,返回將str1編輯成str2的最小代價。舉例:str1="abc"   str2="adc"  ic=5    dc=3

動態規劃編輯距離(字串A到字串B變化最少要多少步)

最小編輯距離是一道非常經典的動態規劃問題。 設A 和B 是2 個字串。要用最少的字元操作將字串A 轉換為字串B。  這裡所說的字元操作包括  (1)刪除一個字元;  (2)插入一個字元;  (3)將一個字元改為另一個字元。  將字串A變換為字串B 所用的最少字元操作次數也稱

動態規劃長不下降序列

求最長不下降序列求最長不下降序列求最長不下降序列 Description 設有n(n<=1000)個不相同的整數(小於32767)組成的數列,記為: a1,a2,…,an,其中任意兩個數不相同。

動態規劃--長無重複子串

給定一個字串,找出不含有重複字元的最長子串的長度。 示例: 給定 "abcabcbb" ,沒有重複字元的最長子串是 "abc" ,那麼長度就是3。 給定 "bbbbb" ,最長的子串就是 "b" ,長度是1。 給定 "pwwkew" ,最長子串是 "wke" ,長度是3。請注

動態規劃大子矩陣之和

最大子矩陣之和 題目描述 已知矩陣的大小定義為矩陣中所有元素的和。給定一個矩陣,你的任務是找到最大的非空(大小至少是11)子矩陣。 比如,如下44子矩陣 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2 的最

leetcode 矩陣中的長遞增路徑 python動態規劃

題目描述 **分析:**假設最長路徑終點的是[i][j],則其最長路徑值為nums1[i][j],則nums1[i][j]等於它上下左右四個數中,比它小的數中最長路徑值最大的那一個+1 因此,我們可以從矩陣的最小值出發,其最長路徑值為1,然後計算第二小的數的最長路徑值,以此類推 cla

動態規劃短路[BZOJ 1003]物流運輸trans

簡直是醉了,這道題本來想了一會兒,然後看了看資料邊的數量頂天了才400然後時間最多才100那麼直接用SPFA 複雜度O(nm2)就可以過了,然後注意一下特別判定是否超過INF可能有資料很極限,判斷一下是

動態規劃數字三角形大值(一)(遞迴)

題目:數字三角形,形如          3      3      2   4     5     1 1    3     4     1 每個點只能選擇向左或向右走,取一條路徑,使得路徑上數字和最大。 無需求出路徑,求出最大值。 輸入n,和 n 行數字三角形 n<

動態規劃長公共子串,長迴文子串

題目 : 給定兩個字串,求出它們之間連續的最長的相同子字串的長度。 eg : fbaabe,ebaabf,連續最長子串長度為4。 注意:求最長迴文子串也可以用求最長公共子串來求,只需將字串反轉作為另外一個字串,迴文部分反轉之後不變,然後求LCS(Longes

動態規劃求一維子陣列的大和

題目:輸入一個整形陣列,數組裡有正數也有負數。陣列中連續的一個或多個整陣列成一個子陣列,每個子陣列都有一個和。求所有子陣列的和的最大值。要求時間複雜度為O(n)。 例如,輸入的陣列為1, -2, 3,

動態規劃長公共子序列與長公共子串

1. 問題描述 子串應該比較好理解,至於什麼是子序列,這裡給出一個例子:有兩個母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs與belong中都出現過並且出現順序與母串保持一致,我們將其稱為公共子序列。最長公共子序列(Longest Common Subsequence

0020演算法筆記——動態規劃優二叉搜尋樹問題

 1、問題描速: 設 S={x1, x2, ···, xn} 是一個有序集合,且x1, x2, ···, xn表示有序集合的二叉搜尋樹利用二叉樹的頂點儲存有序集中的元素,而且具有性質:儲存於每個頂點中的元素x 大於其左子樹中任一個頂點中儲存的元素,小於其右子

2017年A組藍橋杯(大公共子串問題)動態規劃

最大公共子串長度問題就是:求兩個串的所有子串中能夠匹配上的最大長度是多少。比如:"abcdkkk" 和"baabcdadabc",可以找到的最長的公共子串是"abcd",所以最大公共子串長度為4。下面的程式是採用矩陣法進行求解的,這對串的規模不大的情況還是比較有效的解法。請分