Cake ZOJ

来源:互联网 发布:怎么开店淘宝店 编辑:程序博客网 时间:2024/05/18 00:53

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 iscosti, 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 andp (3 ≤ N, p ≤ 300), indicating the number of vertices. Each line of the followingN 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 30 01 10 2
Sample Output
0 
意思:给一个多边形,首先判断是不是凸的,然后让你吧多边形划分为相交的三角形,每次划一条边都有对应权值,问你划分完之后最小权值和是多少.

首先看了一波论文,这里不再赘述,--------最后得到一个转移方程,这时候需要观察一下方程,来确定如何递推,比如这道提就是反着推的,因为只有这样推他的子状态才是知道的.

另外,还有dp数组赋值的问题,这些都要看具体的情况来定,最好是先从小的开始手动跑一下试试,然后再进行下一步的调整

///凸边形求最优三角剖分///难点:1.找到一个子状态2.确定转移方程3.会写dp顺序4.会确定dp初始点,四个调教缺一不可#include<bits/stdc++.h>using namespace std;const int M=1000;struct point{    int x,y;};point List[M];int Stack[M],top,dp[388][366],cost[388][366];int cross(point p0,point p1,point p2){    return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);}double dis(point p1,point p2){    return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));}bool cmp(point p1,point p2){    int tmp=cross(List[0],p1,p2);    if(tmp>0)return 1;    else if(tmp==0&&dis(List[0],p1)<dis(List[0],p2))return 1;    else return 0;}void graham(int n){    if(n==1)    {        top=0;        Stack[0]=0;    }    if(n==2)    {        top=1;        Stack[0]=0;        Stack[1]=1;    }    if(n>2)    {        for(int i=0; i<=1; i++)Stack[i]=i;        top=1;        for(int i=2; i<n; i++)        {            while(top>0&&cross(List[Stack[top-1]],List[Stack[top]],List[i])<=0)top--;            Stack[++top]=i;        }    }}int main(){    int n,p;    point p0;    while(scanf("%d%d",&n,&p)!=EOF)    {        scanf("%d%d",&List[0].x,&List[0].y);        memset(cost,0,sizeof(cost));        p0.x=List[0].x;        p0.y=List[0].y;        int k=0;        for(int i=1; i<n; i++)        {            scanf("%d%d",&List[i].x,&List[i].y);            if(p0.y>List[i].y||((p0.y==List[i].y)&&(p0.x>List[i].x)))            {                p0=List[i];                k=i;            }        }        List[k]=List[0];        List[0]=p0;        sort(List+1,List+n,cmp);        graham(n);        if(top!=n-1)        {            printf("I can't cut.\n");            continue;        }        memset(cost,0,sizeof(cost));        for(int i=0; i<n; i++)            for(int j=i+2; j<n; j++)                cost[j][i]=cost[i][j]=abs(List[i].x+List[j].x)*abs(List[i].y+List[j].y)%p;        for(int i=0; i<n; i++)        {            for(int j=i; j<n; j++) dp[i][j]=0x3f3f3f3f;            dp[i][i+1]=0;        }        for(int i=n-3; i>=0; i--)        {            for(int j=i+2; j<n; j++)            {                for(int k=i+1; k<j; k++)                    dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+cost[i][k]+cost[k][j]);            }        }        printf("%d\n",dp[0][n-1]);    }}


原创粉丝点击