CF1572E Polygon

感觉是一道很牛的题。

首先有一个已知顶点坐标求三角形面积的公式:

\[S=\frac{1}{2}((x_2-x_1)(y_4-y_1)-(y_2-y_1)(x_3-x_1)) \]

首先最小值最大,有可能是二分答案。也就是说我们快速 \(\text{check}\) 将该多边形分解成若干个面积大于等于某个值的最大个数。

考虑区间 \(\text{dp}\) 来求解这个东西,具体的用 \(f_{l,r}\) 表示当前区间的可以割出的最多的满足面积大于等于 \(k\) 的个数,\(g_{l,r}\) 表示在满足割出的多边形最多的情况下剩下的最大面积。这个东西考虑转移的就是考虑合并两个区间的时候中间还会多出一个三角形,将三角形和剩余面积比较一下能否拼出一个满足要求的多边形,同时更新一波答案即可。

#include<bits/stdc++.h>
using namespace std;
const int N=2e2+5;
int n,k;
struct Point{long long x,y;}a[N];
pair<int,long long> f[N][N];
long long cal(Point a,Point b,Point c){
	return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
int check(long long k){
	for(int len=3;len<=n;++len){
		for(int i=1,j=len;j<=n;++i,++j){
			f[i][j]=make_pair(0,0);
			for(int c=i+1;c<j;++c){
				pair<int,long long> tmp;
				tmp.first=f[i][c].first+f[c][j].first;
				tmp.second=f[i][c].second+f[c][j].second+cal(a[i],a[c],a[j]);
				if(tmp.second>=k) tmp.first++,tmp.second=0;
				f[i][j]=max(f[i][j],tmp);
			}
		}
	}
	return f[1][n].first;
}
int main(){
	cin>>n>>k;
	for(int i=1;i<=n;++i)
		scanf("%lld%lld",&a[i].x,&a[i].y);
	long long L=0,R=8e16,res=-1;
	while(L<=R){
		long long Mid=(L+R)>>1;
		
		if(check(Mid)>k) L=Mid+1,res=Mid;
		else R=Mid-1;
	}
	return printf("%lld\n",res),0;
}
posted @ 2021-12-21 10:53  Point_King  阅读(63)  评论(1)    收藏  举报