UVA-1331Minimax Triangulation
来源:互联网 发布:阿里云青岛机房位置 编辑:程序博客网 时间:2024/05/21 11:37
Brief description
略
Algorithm analyse
区间dp与几何联系的题目,
dp过程:区间dp,dp[i][j]表示的区间i到j的最大面积的最小值。
我的dp的思路是模仿LRJ的模板,枚举左节点,枚举右节点。然后枚举中间的节点。
一个技巧。在枚举的过程中初始化,这题2个相邻节点,即同一条边的相邻节点的值为0,
然后再进行初始化为INF,判断是i,j,k是否能构成满足条件的三角形.
满足条件。 dp[i][j]=min(dp[i][j],max(max(dp[i][k],dp[k][j]),area(p[i],p[k],p[j])));
返回 dp[0][n-1]即可。
判断是i,j,k是否能构成满足条件的三角形。
计算几何问题,注意精度问题。
3个点用叉积求三角形面积。3条件用海伦公式求三角形面积。
关于叉积,我参考LRJ的代码时,他就是用叉积来做的。里面有几点判断是否满足构成三角形,我看不懂。
然后参考了别人的博客,他说只需判断是否在三角里面即可。这点我也不理解。
首先贴上与叉积有关的概念和闭包代码。
叉积
然后是参考的博客
参考博客
Code
LRJ的代码
// UVa1331 Minimax Triangulation// Rujia Liu#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<vector>#include<queue>#include<algorithm>using namespace std;const double eps = 1e-10;int dcmp(double x) { if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;}struct Point { double x, y; Point(double x=0, double y=0):x(x),y(y) { }};typedef Point Vector;Vector operator + (const Vector& A, const Vector& B) { return Vector(A.x+B.x, A.y+B.y); }Vector operator - (const Point& A, const Point& B) { return Vector(A.x-B.x, A.y-B.y); }Vector operator * (const Vector& A, double p) { return Vector(A.x*p, A.y*p); }bool operator < (const Point& a, const Point& b) { return a.x < b.x || (a.x == b.x && a.y < b.y);}bool operator == (const Point& a, const Point &b) { return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;}double Dot(const Vector& A, const Vector& B) { return A.x*B.x + A.y*B.y; }double Cross(const Vector& A, const Vector& B) { return A.x*B.y - A.y*B.x; }double Length(Vector A) { return sqrt(Dot(A, A)); }bool SegmentProperIntersection(const Point& a1, const Point& a2, const Point& b1, const Point& b2) { double c1 = Cross(a2-a1,b1-a1), c2 = Cross(a2-a1,b2-a1), c3 = Cross(b2-b1,a1-b1), c4=Cross(b2-b1,a2-b1); return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;}bool OnSegment(const Point& p, const Point& a1, const Point& a2) { return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0;}typedef vector<Point> Polygon;int isPointInPolygon(const Point& p, const Polygon& poly){ int n = poly.size(); int wn = 0; for(int i = 0; i < n; i++){ const Point& p1 = poly[i]; const Point& p2 = poly[(i+1)%n]; if(p1 == p || p2 == p || OnSegment(p, p1, p2)) return -1; // 在边界上 int k = dcmp(Cross(p2-p1, p-p1)); int d1 = dcmp(p1.y - p.y); int d2 = dcmp(p2.y - p.y); if(k > 0 && d1 <= 0 && d2 > 0) wn++; if(k < 0 && d2 <= 0 && d1 > 0) wn--; } if (wn != 0) return 1; // 内部 return 0; // 外部}const int maxn = 100 + 5;bool isDiagonal(const Polygon& poly, int a, int b) { int n = poly.size(); for(int i = 0; i < n; i++) if(i != a && i != b && OnSegment(poly[i], poly[a], poly[b])) return false; // 中间不能有其他点 for(int i = 0; i < n; i++) if(SegmentProperIntersection(poly[i], poly[(i+1)%n], poly[a], poly[b])) return false; // 不能和多边形的边规范相交 Point midp = (poly[a] + poly[b]) * 0.5; return (isPointInPolygon(midp, poly) == 1); // 整条线段在多边形内}const double INF = 1e9;double d[maxn][maxn];double solve(const Polygon& poly) { int n = poly.size(); for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) d[i][j] = -1; for(int i = n-2; i >= 0; i--) for(int j = i+1; j < n; j++) { if(i + 1 == j) d[i][j] = 0; else if(!(i == 0 && j == n-1) && !isDiagonal(poly, i, j)) d[i][j] = INF; else { d[i][j] = INF; for(int k = i+1; k < j; k++) { double m = max(d[i][k], d[k][j]); double area = fabs(Cross(poly[j]-poly[i], poly[k]-poly[i])) / 2.0; // triangle i-j-k m = max(m, area); d[i][j] = min(d[i][j], m); } } } return d[0][n-1];}int main() { int T, n; scanf("%d", &T); while(T--) { scanf("%d", &n); double x, y; Polygon poly; for(int i = 0; i < n; i++) { scanf("%lf%lf", &x, &y); poly.push_back(Point(x,y)); } printf("%.1lf\n", solve(poly)); } return 0;}
#include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #include <queue> #include <stack> #include <functional> #include <set> #include <cmath> using namespace std; #define pb push_back #define PB pop_back #define bk back() #define fs first #define se second #define sq(x) (x)*(x) #define eps (1e-10) #define INF (0x3f3f3f3f) #define clr(x) memset((x),0,sizeof (x)) #define cp(a,b) memcpy((a),(b),sizeof (b)) typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> P; const int maxn=105;int n;struct point{double x,y;void get(){scanf("%lf%lf",&x,&y);}}p[maxn];double d[maxn][maxn];double area (point a, point b, point c) { return fabs((b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y))/2; } bool judge (int a, int b, int c) { double cur = area(p[a], p[b], p[c]); for (int i = 0; i < n; i++) { if (i == a || i == b || i == c) continue; double tmp = area(p[a], p[b], p[i]) + area(p[b], p[c], p[i]) + area(p[c], p[a], p[i]); if (fabs(tmp - cur) < eps) return false; } return true; } double solve(){for(int i=0;i<n;i++)for(int j=0;j<n;j++) d[i][j]=-1;for(int i=n-2;i>=0;i--)for(int j=i+1;j<n;j++){if(j==i+1) d[i][j]=0;else{d[i][j]=INF;for(int k=i+1;k<j;k++){if(judge(i,k,j)){d[i][j]=min(d[i][j],max(max(d[i][k],d[k][j]),area(p[i],p[k],p[j])));}}}}return d[0][n-1];}int main(){int cas;scanf("%d",&cas);while(cas--){scanf("%d",&n);for(int i=0;i<n;i++) p[i].get();printf("%.1lf\n",solve());}return 0;}
回到之前的问题,最优矩阵链乘和最优三角剖分的不同点,现在明白了。最优矩阵链乘是的决策都是顺序话化了,而最优矩阵剖分则没有。
举个例子
比如i=5,k=10,j=20,n=40中.
这样就有多个多边形。0到5,5到10,10到20,20到40.并且在这些多边形中也是可以随意划分的,这样状态转移方程不好写。
所以定个序。0-n之间的k,然后0到k,k到n。这样,然后定个区间以及顺序就可以了。
0 0
- UVa 1331 Minimax Triangulation
- UVA-1331Minimax Triangulation
- uva 1331 Minimax Triangulation
- UVA 1331 Minimax Triangulation
- uva 1331 - Minimax Triangulation(dp)
- UVa OJ 1331 - Minimax Triangulation
- UVA 1331 Minimax Triangulation 区间DP
- uva 1331——Minimax Triangulation
- Minimax Triangulation UVA
- UVA 1331Minimax Triangulation——最优三角剖分
- 1331 - Minimax Triangulation(DP)
- Uva 1331 - Minimax Triangulation(最优三角剖分 区间DP)
- UVA 1331 Minimax Triangulation [最优三角剖分] [dp] [计算几何]
- 1331 - Minimax Triangulation (区间DP+几何)
- UVALive 3132 Minimax Triangulation
- hdu 1966 Minimax Triangulation
- UVA 1331 Minimax Triangulation 最大面积最小的三角剖分(区间dp--记忆化搜索)
- Minimax Triangulation - POJ 2066 dp+几何
- Java Web学习笔记——Servlet
- 第十五周 项目1-验证算法(2)
- pc前端开发小经验
- 理解和掌握类的加载过程以及子类继承父类后,重写方法的调用问题
- 第十五周项目(2):用哈希法组织关键字2——用链地址法处理冲突
- UVA-1331Minimax Triangulation
- javascript中闭包函数的作用
- 第十三周实践项目~Prim算法的验证
- 第14周项目2-二叉树排序树中查找的路径
- 有向图(7)--再谈可达性&&有向图总结
- 设置沉浸式状态栏
- 第十一周项目二:用二叉树求解代数表达式
- init()方法调用及扩展
- java默认构造器constructor