现在的位置: 首页 > 综合 > 正文

UVA – 1331(与几何相关dp)

2019年04月03日 ⁄ 综合 ⁄ 共 2558字 ⁄ 字号 评论关闭

首先,来说以个问题;若该多边形为凸多边形的话,

那么设 d(i,j)代表以i节点为起点以j为最后一个点组成的多边形的最大面积最小的剖分;

有状态转移式子 d(i,j) = min( d[i][j] , max( max(d(i,k),d(k,j) ),s(i,k,j) ))  (其中i<k<j ,s(i,k,j)为三点组成的三角形面积);

但对于不是凸多边形的话,上述式子在对k决策时,要额外满足一个条件i-->k,k-->j 两条线段必须都是多边形的对角线;

判断是否为对角线的话

首先该线段不和任一条边相交(不包括在端点相交),其次该线段在多边形内部;(判断第二个条件时,因为没啥好办法,就在线段上选了一个点(与任意顶点不同)来判断该

点是否在多边形内部;

#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
const int inf = 1e9;
const int maxn = 55;
const double eps = 1e-10;
struct point{
  double x,y;
  point(double x=0,double y=0):x(x),y(y){}
}a[maxn];
double cross(point a,point b){
  return a.x*b.y-a.y*b.x;
}
double dot(point a,point b){
  return a.x*b.x+a.y*b.y;
}
point operator *(point a,double c){
  return point(a.x*c+a.y*c);
}
point operator -(point a,point b){
  return point(a.x-b.x,a.y-b.y);
}
int dcmp(double x){
  if(fabs(x) < eps) return 0;
  else return x<0 ? -1 : 1;
}
double trianglearea(point a,point b,point c){
  return fabs(cross(b-a,c-a))/2.0;
}
bool SegmentProperIntersection(point a1,point a2,point b1,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;
}
/*not include point in each side;*/
bool isPointOnSegment(point p,point a1,point a2){
  return dcmp(cross(a1-p,a2-p))==0 && dcmp(dot(a1-p,a2-p))<0;
}
int isPointinPolygon(point p){
  int wn = 0;
  for(int i=0;i<n;i++){
    if(isPointOnSegment(p,a[i],a[(i+1)%n])) return -1;
    int k = dcmp(cross(a[(i+1)%n]-a[i],p-a[i]));
    int d1 = dcmp(a[i].y-p.y);
    int d2 = dcmp(a[(i+1)%n].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;
}
bool Judge(int i,int j){
  if(i+1==j) return true;
  for(int k=0;k<n;k++){
    if(SegmentProperIntersection(a[i],a[j],a[k],a[(k+1)%n]))
        return false;
  }
  point c=a[i],d=a[j];
  if(a[i].y > a[j].y){
      swap(c.y,d.y);
      swap(c.x,d.x);
  }
  point temp;
  double fenmu = 50.0;
  for(int k=1;k<=40;k++){
      double dx = fabs((c.x-d.x))*k/fenmu;
      double dy = fabs((c.y-d.y))*k/fenmu;
      if(c.x < d.x){
         temp.x = d.x - dx;
         temp.y = d.y - dy;
      }
      else {
         temp.x = d.x + dx;
         temp.y = d.y - dy;
      }
      int ok = 1;
      for(int g=0;g<n;g++){
         if(dcmp(a[g].x-temp.x)==0 &&dcmp(a[g].y-temp.y)==0){
            ok = 0; break;
         }
      }
      if(ok) break;
  }
  if(isPointinPolygon(temp)==1) return true;
  return false;
}
double d[maxn][maxn];
bool vis[maxn][maxn];
double dp(int i,int j){
   if(vis[i][j]) return d[i][j];
   vis[i][j] = true;
   if(i+1==j){return d[i][j]=0;}
   d[i][j] = inf;
   for(int k=i+1;k<j;k++){
      if(!Judge(i,k)||!Judge(k,j)) continue;
      double s = trianglearea(a[i],a[k],a[j]);
      d[i][j]=min(d[i][j],max(max(dp(i,k),dp(k,j)),s));
   }
   return d[i][j];
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
      scanf("%d",&n);
      for(int i=0;i<n;i++){
        scanf("%lf %lf",&a[i].x,&a[i].y);
      }
      memset(vis,false,sizeof(vis));
      printf("%.1lf\n",dp(0,n-1));
    }
    return 0;
}

抱歉!评论已关闭.