凸包DP问题-codevs1273风战&ZOJ1562The Picnic

传送门:
codevs1273
zoj1562


codevs1273

将点按极角排序, g [ i ] [ j ] g[i][j] g[i][j]表示点 i , j i,j i,j和基点围成的三角形内所有点的总价值。 d p [ i ] [ j ] dp[i][j] dp[i][j]表示凸包从基点出发顺时针最后两个点分别为 j , i j,i j,i时的最优答案。

暴力处理 g , d p g,dp g,dp复杂度 O ( n 3 ) O(n^3) O(n3)

优化:
求解 g [ i ] [ j ] g[i][j] g[i][j]时,首先固定 i i i [ i + 1 , n ] [i+1,n] [i+1,n]逐个枚举 j j j,按 i i i j j j的极角大小为权值加入平衡树, g [ i ] [ j ] g[i][j] g[i][j]就是平衡树中在 j j j左边的所有点的总值。复杂度 O ( n 2 log ⁡ n ) O(n^2\log n) O(n2logn)

d p dp dp时枚举中转点,将所有前驱 j j j i → j i\to j ij极角大小插入 b s t bst bst,维护子树 m a x ( f [ j ] [ i ] ) max(f[j][i]) max(f[j][i]),对于所有后继按反向极角二分插入查询最大值即可。复杂度 O ( n 2 log ⁡ n ) O(n^2\log n) O(n2logn)

代码

暴力 O ( n 3 ) O(n^3) O(n3)

#include<bits/stdc++.h>
typedef long long ll; 
using namespace std;
const int N=105;

struct P{
    int x,y,t;
    P(int _x=0,int _y=0):x(_x),y(_y){}
    inline P operator - (const P&ky){return P(x-ky.x,y-ky.y);}
    inline ll operator * (const P&ky){return (ll)x*ky.y-(ll)y*ky.x;}
    inline bool operator < (const P&ky)const{return atan2(y,x)<atan2(ky.y,ky.x);}
}p[N];
int n,m,ans,g[N][N],f[N][N];

int main(){
	int i,j,k,v;
    scanf("%d%d",&n,&m);
	for(i=1;i<=n;++i) scanf("%d%d",&p[i].x,&p[i].y),p[i].t=1;
    for(i=n+1;i<=n+m;++i) scanf("%d%d",&p[i].x,&p[i].y),p[i].t=-1;
    n+=m;sort(p+1,p+n+1);
    for(i=1;i<=n;++i)
        for(j=i+1;j<=n;++j)
            for(k=i+1;k<j;++k)
                if((p[i]-p[k])*(p[j]-p[k])>0) g[i][j]+=p[k].t;
    for(i=1;i<=n;++i){
        f[i][0]=p[i].t;
        for(j=1;j<i;++j){
            for(v=k=0;k<j;++k)
                if((p[k]-p[i])*(p[j]-p[i])>=0)
                    v=max(v,f[j][k]+g[j][i]+p[i].t);
            ans=max(ans,(f[i][j]=v));
        }
    }
    printf("%d",ans);
    return 0;
}

ZOJ1562

套上一个枚举起点, g [ i ] [ j ] g[i][j] g[i][j]该为与 ( i , j ) (i,j) (i,j)与起点围成三角形中是否存在障碍物。
其余同上。复杂度 O ( n 4 ) O(n^4) O(n4) O ( n 3 log ⁡ n ) O(n^3\log n) O(n3logn)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值