1. 程式人生 > >UVa 1331 最大面積最小的三角剖分(dp)

UVa 1331 最大面積最小的三角剖分(dp)

這裡寫圖片描述
一共有4條邊,我們可以以隨意的順序切割,不過如果這樣的話,就會出現類似v0v3v4v6這樣的多邊形,這樣的多邊形很難用簡潔的狀態表示出來,這就是讓我一開始很糾結的地方。

其實我們會發現,對於同一種切割方法,我們可以有多種切割順序,但我們只要計算一種就好了,不如把決策順序規範化。例如還是上面第一張圖,我們可以先切割出三角形v0v3v6,那麼我們切割完之後可以把圖分割成一個三角形和兩個多邊形,而組成這兩個個多邊形的點的編號都是連續的。

於是我們可以得出一種切割方法,比如我要切割多邊形i,i+1,…,j-1,j(i < j),那麼我下一步切割的三角形一定有i和j這兩個點(這樣的規定並不會出錯,因為無論我們如何切割,分出來的三角形中一定有一個過i和j),而這樣的切割方法的優點是保證了每次切出來的多邊形組成的點的編號都是連續的,於是我們就可以用兩個元素表示一個多邊形的狀態了,這樣dp轉移方程很容易可以得出來:

d(i,j)=min{max(d(i,k),d(k,j),S(i,j,k))|i < k< j};

其中,S(i,j,k)為三角形i-j-k的面積。不過此時需要保證i-j是對角線(唯一的例外是i=0且j=n-1),具體做法是當邊i-j不滿足條件時直接設為INF,其他部分和凸多邊形的情形完全一樣。

這裡用海倫公式計算三角形面積
用面積差判斷三角形內部是否有點
明確了這些進行dp
最後答案在d[1][N]中
d[i][j]表示的是以i,j為邊界不包含序號1的點的多邊形裡最大三角形面積最小值

#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 大面積三角(dp)

一共有4條邊,我們可以以隨意的順序切割,不過如果這樣的話,就會出現類似v0v3v4v6這樣的多邊形,這樣的多邊形很難用簡潔的狀態表示出來,這就是讓我一開始很糾結的地方。 其實我們會發現,對於同一種切割方法,我們可以有多種切割順序,但我們只要計算一種就好

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

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

動態規劃 凸 n 邊形三角周長

題目輸入凸 n 邊形 p 1 ,p 2 ,··· ,p n , 其中頂點按凸多邊形邊界的逆時針序給出,多邊形中不相鄰頂點間的連線稱為弦。試設計一個動態規劃演算法,用若干條弦將凸邊形 p 1 ,p 2 ,··· ,p n 剖分成一些無公共區域的三角形,使得所有三角形的周長之和最

三角

return min std esp div 技術分享 include %d logs 同樣是紫書上的題。 紫書上並沒有給出每一個三角形所貢獻的的權值的計算方法,我這裏就擅作主張,定義成點權的乘積和好了。 那麽做法是DP,這裏註意設狀態的方式(我這麽設是為了使需要求解的問題

凸多邊形三角(演算法設計:動態規劃)

一、動態規劃       和分治法類似,把原問題劃分成若干個子問題,不同的是,分治法(子問題間互相獨立),動態規劃(子問題不獨立)       動態規劃: (1)找出最優解的性質,刻畫其結構特徵 (2)遞迴地定義最優值

動態規劃之凸多邊形三角

 問題描述 多邊形是平面上一條分段線性的閉曲線。也就是說,多邊形是由一系列首尾相接的直線段組成的。組成多邊形的各直線段稱為該多邊形的邊。多邊形相接兩條邊的連線點稱為多邊形的頂點。若多邊形的邊之間除了連線頂點外沒有別的公共點,則稱該多邊形為簡單多邊形。一個簡單多邊形將平面分為3個部分:被包圍

動態規劃-凸多邊形三角問題

一、 問題描述 多邊形是平面上一條分段線性的閉曲線。也就是說,多邊形是由一系列首尾相接的直線段組成的。組成多邊形的各直線段稱為該多邊形的邊。多邊形相接兩條邊的連線點稱為多邊形的頂點。若多邊形的邊之間除了連線頂點外沒有別的公共點,則稱該多邊形為簡單多邊形。一個簡

凸多邊形三角(動態規劃)

#include<stdio.h> #include<stdlib.h> #include<iostream> using namespace std; const int N=7; int Weight(int **w,int a,int b,int c) {     r

【動態規劃】凸多邊形三角

 經典dp問題  1、問題相關定義:  (1)凸多邊形的三角剖分:將凸多邊形分割成互不相交的三角形的弦的集合T。 (2)最優剖分:給定凸多邊形P,以及定義在由多邊形的邊和絃組成的三角形上的權函式w。要求確定該凸多邊形的三角剖分,使得該三角剖分中諸三角形上權之和為最小。

0014演算法筆記——【動態規劃】凸多邊形三角

1、問題相關定義: (1)凸多邊形的三角剖分:將凸多邊形分割成互不相交的三角形的弦的集合T。 (2)最優剖分:給定凸多邊形P,以及定義在由多邊形的邊和絃組成的三角形上的權函式w。要求確定該凸多邊形的三角剖分,使得該三角剖分中諸三角形上權之和為最小。      凸多邊形三

凸多邊形三角的兩種演算法分析

/* Name: Copyright: Author: 巧若拙 Date: 27-03-17 10:11 Description: 動態規劃--凸多邊形最優三角剖分 題目描述: 用多邊形頂點的逆時針序列表示凸多邊形,即P={v0,v1,…,vn

zoj 3537 Cake 【凸包 + 區間dp】 【三角

Cake Time Limit: 1 Second      Memory Limit: 32768 KB You want to hold a party. Here's a polygon-shaped cake on the table. You'd like t

【bzoj2238】Mst 小生成樹+樹鏈+線段樹

生成樹 brush 輸出 兩個 下一條 整數 algorithm ted sin 題目描述 給出一個N個點M條邊的無向帶權圖,以及Q個詢問,每次詢問在圖中刪掉一條邊後圖的最小生成樹。(各詢問間獨立,每次詢問不對之後的詢問產生影響,即被刪掉的邊在下一條詢問中依然存在) 輸

短路 BZOJ3694 樹鏈+線段樹

OS 情況 ostream 最小值 down from == spa sizeof 分析: 樹剖裸題,[Usaco2009 Jan]安全路經Travel 的簡化版 剖開最短路樹,遍歷每一條沒在最短路樹上的邊。 這種情況下,有且僅有u到v路徑上,出來lca之外的點能夠通

P4949 短距離(樹鏈+樹狀陣列+基環樹)

傳送門 一箇中午啊…… 本來打算用仙人掌搞的,後來發現直接基環樹就可以了,把多出來的那條邊單獨記錄為\((dx,dy,dw)\),剩下的樹剖 然後最短路徑要麼直接樹上跑,要麼經過多出來的邊,分別討論就好了 因為這裡的樹剖只有單點修改和區間查詢,於是可以用樹狀陣列 //minamoto #include&l

Codeforces 827D Best Edge Weight (小生成樹 + 樹鏈/倍增/並查集)

Codeforces 827D Best Edge Weight 題意: 給你N個點M條邊的帶邊權無向聯通圖,現在對於每條邊,問這條邊的權值最大可以是多 少,使得這條邊在該無向圖的所有最最小成樹中? 資料範圍 2 ≤N ≤ 2*1055, N - 

bzoj4449: [Neerc2015]Distance on 點分治 三角 平面圖與對偶圖

bzoj4449: [Neerc2015]Distance on Triangulation Description 給定一個凸n邊形,以及它的三角剖分。再給定q個詢問,每個詢問是一對凸多邊行上的頂點(a,b),問點a最少經過多少條邊(可以是多邊形上的邊,也可以是剖分上的邊)可以

opencv平面三角Delaunay

opencv使用: Subdiv2D  實現三角剖分。 使用參考:https://blog.csdn.net/czl389/article/details/62264960?fps=1&locationNum=5  關於三角剖分的基本知識參考:

VC+OpenGL實現空間三維Delaunay三角

 三維建模和等值面的繪製過程中,需要經常使用三角形網格對資料體進行構面。而三角形的生成基於Delaunay三角剖分的演算法實現的。前段時間一直在考慮資料體的任意剖面切割該怎麼做,但是一直被兩個問題所困擾,一個就是交點問題,然後就是對所求交點進行繪製問題(三角形網格面構造)。終於在半個月後有

PICK定理與三角

//PICK定理:S=I+E/2-1,a多邊形內部的點數,b多邊形邊界上的點數,S多邊形的面積 #include <bits/stdc++.h> using namespace std; struct node{int x,y;}p[200]; int n,S,E,I;//N個點