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

#include <stdio.h>
#include <iostream>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
struct node
{
	int x,y;
	bool operator<(const node &a)const{    //x从小到大 x相等 y从小到大
		if(x==a.x)return y<a.y;
		return x<a.x;
	}
}p[400],a[400];
node operator-(node a,node b)
{
	node tem={a.x-b.x,a.y-b.y};
	return tem;
}
int n,m;
int d[400][400],f[400][400];

double Cross(node A,node B)
{
	return A.x*B.y-A.y*B.x;
}
int ConvexHull() //求出满足凸包个数
{
	sort(p,p+n);
	int cnt=0;
	for(int i=0;i<n;i++)
	{
		while(cnt>1&&Cross(a[cnt-1]-a[cnt-2],p[i]-a[cnt-2])<=0)cnt--;//两条边叉积要>0,从左到右
		a[cnt++]=p[i];
	}
	int k=cnt;
	for(int i=n-2;i>=0;i--) //从右到左
	{
		while(cnt>k&&Cross(a[cnt-1]-a[cnt-2],p[i]-a[cnt-2])<=0)cnt--;
		a[cnt++]=p[i];
	}
	if(n>1)cnt--;
	return cnt;
}
int dfs(int x,int y)
{
	if(d[x][y]!=-1)return d[x][y];
	if(y-x<=2)return 0;
	d[x][y]=1e9;
	int i;
	for(i=x+1;i<y;i++)
		d[x][y]=min(dfs(x,i)+dfs(i,y)+f[x][i]+f[i][y],d[x][y]);
	//printf("%d %d %d %d %d\n",x,y,d[x][y],f[x][i],f[i][y]);
	return d[x][y];
}
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		memset(d,-1,sizeof(d));
		for(int i=0;i<n;i++)
			scanf("%d%d",&p[i].x,&p[i].y);
		if(n==3)
		{
			puts("0");
			continue;
		}
		if(ConvexHull()<n)puts("I can't cut.");
		else
		{
			//for(int i=0;i<n;i++)printf("%d %d\n",a[i].x,a[i].y);
			for(int i=0;i<n;i++)
				for(int j=i+2;j<n;j++)
					f[i][j]=f[j][i]=abs(a[i].x+a[j].x)*abs(a[i].y+a[j].y)%m;
			printf("%d\n",dfs(0,n-1));
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值