Game of Taking Stones && 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;
double add(double a,double b) {
    if(abs(a+b)<eps*(abs(a)+abs(b))) return 0;
    return a+b;
} // 考虑误差
int dcmp(double x) {
    if(abs(x)<eps) return 0;
    else return x<0 ? -1:1;
}
struct P {
    double x,y;
    P(){};
    P(double _x,double _y):x(_x),y(_y){}
    P operator -(P p) { return P(add(x,-p.x),add(y,-p.y)); };
    P operator +(P p) { return P(add(x,p.x),add(y,p.y)); };
    P operator *(double d) { return P(x*d,y*d); };
    double dot(P p) { return add(x*p.x,y*p.y); }; // 点积为0垂直
    double det(P p) { return add(x*p.y,-y*p.x); }; // 叉积为0平行
    void scf() { scanf("%lf%lf",&x,&y); }
}pa[105], p[105], O;
double lenV(P v) { return sqrt(v.dot(v)); }
bool cmp(P a,P b) {
    int f=dcmp((a-O).det(b-O));
    if(f==0) return lenV(a-O)<lenV(b-O);
    return f>0;
}

double dp[105][105], ans;

void MEP(int n) {
    sort(p,p+n,cmp);
    memset(dp,0,sizeof(dp));
    for(int i=0;i<n;i++) { // O-i 始终作为以st开始的凸包顺时针的第一条边
        int j=i-1;
        while(j>=0 && dcmp((p[i]-O).det(p[j]-O))==0) j--;
        // i-j 作为凸包的第二条边
        bool flag=(j==i-1);
        while(j>=0) {
            int k=j-1;
            while(k>=0 && dcmp((p[i]-p[k]).det(p[j]-p[k]))>0) k--;
            // 找到能作为凸包右下的一点的 k
            double area=abs((p[i]-O).det(p[j]-O))/2.0;
            if(k>=0) area+=dp[j][k]; // 已求得的jk的MEP + 三角形Oij
            if(flag) dp[i][j]=area; /// j!=i-1时不更新dp数组
            /** 虽然对当前的凸包来说只是边界点没影响
                但是之后其他凸包需利用当前dp[i][j]时
                这些边界点会被包含在凸包内 */
            ans=max(ans,area);
            j=k;
        }
        if(flag)
            for(int j=1;j<i;j++)
                dp[i][j]=max(dp[i][j],dp[i][j-1]);
    }
}

int main()
{
    int t; scanf("%d",&t);
    while(t--) {
        int n; scanf("%d",&n);
        ans=0;
        for(int i=0;i<n;i++) pa[i].scf();
        for(int i=0;i<n;i++) {
            O=pa[i];
            int c=0;
            for(int j=0;j<n;j++)
                if(pa[j].y>pa[i].y || dcmp(pa[j].y-pa[i].y)==0&&pa[j].x>pa[i].x)
                    p[c++]=pa[j]; // 取O右上角的点
            MEP(c); //printf("%.1f\n",ans);
        }
        printf("%.1f\n",ans);
    }

    return 0;
}

原文地址:https://www.cnblogs.com/zquzjx/p/9986422.html

时间: 2024-10-08 11:13:50

Game of Taking Stones && POJ1259 /// 最大空凸包 几何+DP的相关文章

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> #

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

HDU 4573 Throw the Stones(动态三维凸包)(2013 ACM-ICPC长沙赛区全国邀请赛)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4573 Problem Description Remember our childhood? A few naked children throw stones standing on the same position, the one throws farther win the game. Aha, of course, there are some naughty boys who care

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

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

最大空凸包模板

inline double sgn(double x, double y) { return fabs(x-y)<eps; } inline int sgn(int x, int y) { return x==y; } struct point { double x,y; }; double cross(point a, point b, point o) { return (a.x-o.x)*(o.y-b.y)-(a.y-o.y)*(o.x-b.x); } double dist(point

最大空凸包

#pragma GCC optimize(2) #pragma GCC optimize(3, "Ofast", "inline") #include<bits/stdc++.h> #define ll long long #define met(a, x) memset(a,x,sizeof(a)) using namespace std; const double pi = acos(-1.0); typedef struct Point { int

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