凸包 + 最优三角剖分_ZOJ 3735

题目链接

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4472

题目解析

题目中有一个蛋糕,要求尽可能的分割蛋糕,并且每一个对角线的切割都有一定的消费,要求计算消费最小,并且如果这个多边形不满足凸包,直接输出"I can't cut."

题目相对于最优三角划分,只是多了一个凸包的判断,并且这也就是一个模板题目,可以直接使用Graham扫描法的模板计算,然后如果是凸包,那么再去计算最优的划分消耗

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <math.h>
#include <queue>
#define INF 0x3f3f3f3f

using namespace std;
const int MAXN = 350;
int n,m;
struct Point
{
    int x,y;
}p[MAXN],c[MAXN];
int cost[MAXN][MAXN],dp[MAXN][MAXN];
int mulit(Point p0, Point p1, Point p2)
{
    return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * ( p1.y - p0.y);
}
double dis(Point a,Point b)
{
    return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}

bool cmp(Point a,Point b)
{
    int x = mulit(p[0],a,b);
    if(x > 0 || (x == 0 && dis(p[0],a) < dis(p[0],b))) return true;
    return false;
}

int Get_cost(Point a,Point b)
{
    return abs(a.x + b.x) * abs(a.y +  b.y) % m;
}

int Graham()
{
    if(n == 1) return 0;
    int k = 0;
    for(int i = 1;i < n;i ++)
        if(p[i].y < p[k].y || (p[i].y == p[k].y && p[i].x < p[k].x)) k = i;
    swap(p[0],p[k]);
    sort(p+1,p+n,cmp);
    c[0] = p[0];c[1] = p[1];int tot = 1;
    for(int i = 2;i < n;i ++)
    {
        while(tot && mulit(c[tot-1],c[tot],p[i]) <= 0) tot--;
        c[++tot] = p[i];
    }
    return tot;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(cost,0,sizeof(cost));
        memset(dp,0,sizeof(dp));
        for(int i = 0 ;i < n;i ++)
            scanf("%d%d",&p[i].x,&p[i].y);
        if(Graham() != n-1)
            printf("I can't cut.\n");
        else
        {
            for(int i = 0;i < n;i ++)
                for(int j = i+2;j < n;j ++)
                    cost[i][j] = cost[j][i] = Get_cost(p[i],p[j]);
            for(int i = n-3;i >= 0;i --)
                for(int j = i+2;j < n;j ++)
                {
                    dp[i][j] = INF;
                    for(int k = i+1;k < j;k ++)
                        dp[i][j] = min(dp[i][j],cost[i][k] + cost[j][k] + dp[i][k] + dp[k][j]);
                }
            printf("%d\n",dp[0][n-1]);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/li1615882553/article/details/80199199
今日推荐