zoj3537——最优三角剖分+凸包

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3537

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 vertices of the polygon. Within the polygon, any two cuts ought to be disjoint. Of course, the situation that only the endpoints of two segments intersect is allowed.

The cake's considered as a coordinate system. You have known the coordinates of vexteces. Each cut has a cost related to the coordinate of the vertex, whose formula is costi, j = |xi + xj| * |yi + yj| % p. You want to calculate the minimum cost.

NOTICE: input assures that NO three adjacent vertices on the polygon-shaped cake are in a line. And the cake is not always a convex.

Input

There're multiple cases. There's a blank line between two cases. The first line of each case contains two integers, N and p (3 ≤ N, p ≤ 300), indicating the number of vertices. Each line of the following N lines contains two integers, x and y (-10000 ≤ x, y ≤ 10000), indicating the coordinate of a vertex. You have known that no two vertices are in the same coordinate.

Output

If the cake is not convex polygon-shaped, output "I can't cut.". Otherwise, output the minimum cost.

Sample Input

3 3
0 0
1 1
0 2

Sample Output

0

题目翻译:

你想举行一个聚会。桌子上有一个多边形蛋糕。你想把蛋糕切成几个三角形的零件给受邀的来者。你有一把刀要切。每个切线的跟踪是线段,其两个端点是多边形的两个顶点。在多边形中,任何两个切口都应该不相交。当然,只允许两个段的端点相交的情况。‎

‎蛋糕被认为是一个坐标系。您已经知道了 vexteces 的坐标。每个切口都有与顶点的坐标相关的成本,顶点的公式为 。您想要计算最低成本。‎costi, j = |xi + xj| * |yi + yj| % p

‎注意:输入可确保多边形蛋糕上的三个相邻顶点位于一条线中。蛋糕并不总是凸。‎

‎输入‎

‎有多个案例两种情况之间有一条空白行。每个情况的第一行包含两个整数和 (3 = = 300),指示顶点数。以下行的每行包含两个整数和 (-10000 = = 10000),指示顶点的坐标。您知道没有两个顶点位于同一坐标中。‎NpN, pNxyx, y

 

‎输出‎

‎如果蛋糕不是凸面形,则输出"我无法切割"。否则,输出成本最低。

 

很经典的一道区间dp题,这个题其实如果知道凸包的话,应该就是一道比较好处理的dp题。

这个类似的题写法在刘汝佳紫书(P277)里面讲的有。

状态为dp[i][j]表示从子多边形i到子多边形j的最优值。

状态转移方程为dp[i][j]=max{dp[i][k]+dp[k][j]+w[i][k]+w[k][j]},其中k为能与i和j形成三角形的凸包上的点。

边界条件为dp[i][(i+1)%n]=0;

具体过程不懂得可以看紫书。

#include 
#include
#include
#include
const int INF=0x3f3f3f3f;
using namespace std;
const int maxn=305;
struct Point{
	int x,y;
	Point(){}
    Point(int xx,int yy):x(xx),y(yy){}
	Point operator - (const Point &other)const{
		return Point(x-other.x,y-other.y);
	}
	bool operator < (const Point &other)const{
        return x == other.x?y < other.y:x < other.x;
    }
}p[maxn];
Point save[maxn],tmp[maxn];
int cost[maxn][maxn];
int dp[maxn][maxn];
int n,m;
int Cross(Point a,Point b){//叉积判断位置的左右 
	return a.x*b.y-a.y*b.x;
}
bool ToLeftTest(Point p0,Point p1,Point p2){
	return Cross(p1-p0,p2-p0)>=0;
}
int dis(Point a,Point b){
	return (abs(a.x+b.x)*abs(a.y+b.y))%m;
}
int Graham(){//求凸包的总点数。 
	sort(p,p+n);
	save[0]=p[0];
	save[1]=p[1];
	int top=1;
	for(int i = 0;i=0;i--){
		while(top>mid&&ToLeftTest(save[top],p[i],save[top-1])) top--;
		save[++top]=p[i];
	}
	return top;
}
int main(int argc, char** argv) {
	while(~scanf("%d%d",&n,&m)){
		for(int i = 0;i=0;i--){//i逆序,j顺序因为我们要先知道dp[i][k]和dp[k][j]才能推出dp[i][j] 
				for(int j = i+2;j

 

 

你可能感兴趣的:(区间dp,区间dp,凸包)