POJ1259 The Picnic 最大空凸包问题 DP

POJ1259

给定平面上100个点 求一个最大的凸包,使得它不包含其中任意点,且凸包的顶点是题目所给的点。

枚举凸包左下角的点,顺时针枚举第二个点, 用opt[i][j]记录 i作为第二个点, 且第三个点k在向量i->j的右手(保持凸性)

显然相邻的凸包可以用来转移, opt[j][h]可以加入opt[i][j]  大致思想就是这样 看Solve函数。

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

const int maxn=100;
const double zero=1e-8;
struct Vector
{
 double x,y;
};

inline Vector operator -(Vector a,Vector b)
{
	Vector c;
	c.x=a.x-b.x;
	c.y=a.y-b.y;
	return c;
}

inline double sqr(double a)
{
 return a*a;
}

inline int Sign(double a)
{
 if(fabs(a)<=zero)return 0;
 return a<0 ? -1:1;
}

inline bool operator <(Vector a,Vector b)
{
 return Sign(b.y-a.y)>0||Sign(b.y-a.y)==0&&Sign(b.x-a.x)>0;

}

inline double Max(double a,double b)
{
 return a>b ? a:b;
}

inline double Length(Vector a)
{
 return sqrt(sqr(a.x)+sqr(a.y));
}

inline double Cross(Vector a,Vector b)
{
 return a.x*b.y-a.y*b.x;
}

Vector dot[maxn],List[maxn];
double opt[maxn][maxn];
int seq[maxn];
int n,len;
double ans;

bool Compare(Vector a,Vector b)
{
 int temp=Sign(Cross(a,b));
 if (temp!=0)return temp>0;
 temp=Sign(Length(b)-Length(a));
 return temp>0;
}

void Solve(int vv)
{
 int t,i,j,_len;
 for(int ii=len=0;ii<n;ii++)
 	{
	 if(dot[vv]<dot[ii])List[len++]=dot[ii]-dot[vv];
	}
 for(i=0;i<len;i++)
 	for(j=0;j<len;j++)
 		opt[i][j]=0;
 sort(List,List+len,Compare);
 double v;
 for(t=1;t<len;t++)
 	{
 	 _len=0;
 	 for(i=t-1;i>=0&&Sign(Cross(List[t],List[i]))==0;i--);
 	 //cout<<i<<endl;
 	 while(i>=0)
 	 	{
 	 	 v=Cross(List[i],List[t])/2.;
 	 	 seq[_len++]=i;
 	 	 for(j=i-1;j>=0&&Sign(Cross(List[i]-List[t],List[j]-List[t]))>0;j--);
 	 	 if(j>=0)v+=opt[i][j];
 	 	 ans=Max(ans,v);
 	 	 opt[t][i]=v;
 	 	 i=j;
		}
	 for(i=_len-2;i>=0;i--)
	    opt[t][seq[i]]=Max(opt[t][seq[i]],opt[t][seq[i+1]]);
	}
}

int i;
double Empty()
{
 ans=0;
 for(i=0;i<n;i++)
 	Solve(i);
 return ans;
}
int main()
{freopen("t.txt","r",stdin);
 int T;
 scanf("%d",&T);
 while(T--)
 	{
 	 scanf("%d",&n);
 	 for(int i=0;i<n;i++)
 	 	scanf("%lf%lf",&dot[i].x,&dot[i].y);
 	 printf("%.1lf\n",Empty());
	}
 return 0;
}

  

时间: 2024-10-25 21:10:16

POJ1259 The Picnic 最大空凸包问题 DP的相关文章

Game of Taking Stones &amp;&amp; POJ1259 /// 最大空凸包 几何+DP

题目大意: 给定n个点 求出这n个点中最大空凸包的面积 只放个模板 一份模板过两题(滑稽 这个讲解够详细了 https://blog.csdn.net/nyroro/article/details/45268767 #include <stdio.h> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const double eps=1e-8; dou

HDU6219/POJ1259 [ICPC2017沈阳]Empty Convex Polygons 最大空凸包

Empty Convex Polygons Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 538    Accepted Submission(s): 138 Problem Description Given a set of distinct points S on a plane, we define a convex ho

O(n^3)求最大空凸包模板(2017沈阳icpc-C Empty Convex Polygons )

题目链接:https://vjudge.net/contest/358714#problem/C 题意:求最大空凸包的面积,点的个数n<=50. 思路: 参考链接:https://blog.csdn.net/cdsszjj/article/details/79366813 计算几何+DP. 首先枚举凸包最左下角的点O,忽略O下面的点,对其它点进行极角排序. 然后枚举凸包上的最后一个点i,用dp[i][j]表示以三角形Oij为凸包的最后一块三角形的最大空凸包的面积.那么可以得到转移方程: dp[i

ZOJ 3537 Cake(凸包+区间DP)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3537 题目大意:给出一些点表示多边形顶点的位置,如果不是凸多边形(凸包)则不能切,直接输出"I can't cut."切多边形时每次只能在顶点和顶点间切,每切一次的花费为 cost(i, j) = |xi + xj| * |yi + yj| % p.问把多边形切成最多个不相交三角形的最小代价是多少. 解题思路:先求出凸包,接着可以用区间DP解决,设dp

HDU3045 Picnic Cows(斜率优化DP)

Picnic Cows Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2192    Accepted Submission(s): 675 Problem Description It’s summer vocation now. After tedious milking, cows are tired and wish to t

ZOJ - 3537 Cake (凸包+区间DP+最优三角剖分)

Description You want to hold a party. Here's a polygon-shaped cake on the table. You'd like to cut the cake into several triangle-shaped parts for the invited comers. You have a knife to cut. The trace of each cut is a line segment, whose two endpoin

ZOJ 3537 Cake 求凸包 区间DP

题意:给出一些点表示多边形顶点的位置(如果多边形是凹多边形就不能切),切多边形时每次只能在顶点和顶点间切,每切一次都有相应的代价.现在已经给出计算代价的公式,问把多边形切成最多个不相交三角形的最小代价是多少. 思路:首先判断多边形是否是凸多边形,之后就是区间dp了. 求出凸包后,按逆时针来看. 设置dp[i][j]为从顶点i到顶点j所围成凸多边形的最优解. 枚举切点k (i < k < j) dp[i][j] = min(dp[i][k] + dp[k][j] + cost[i][k] + c

hdu6219(最大空凸包)

题意: 给一些点,求出一个最大的空凸包,这个凸包里没有任何给定点且要求这个凸包面积最大 分析: 枚举凸包左下角的点,然后dp[i][j]表示凸包的最后两条边是j->i和i->O情况下凸包的面积最大值,这个是O(n^4)的 可以利用凸性求个前缀和来完成O(1)的转移 具体看这里:https://blog.csdn.net/nyroro/article/details/45268767 1 #include<bits/stdc++.h> 2 using namespace std; 3

Cake(凸包+区间DP)

You want to hold a party. Here's a polygon-shaped cake on the table. You'd like to cut the cake into several triangle-shaped parts for the invited comers. You have a knife to cut. The trace of each cut is a line segment, whose two endpoints are two v