zoukankan      html  css  js  c++  java
  • ZOJ 3537 Cake 求凸包 区间DP

    题意:给出一些点表示多边形顶点的位置(如果多边形是凹多边形就不能切),切多边形时每次只能在顶点和顶点间切,每切一次都有相应的代价。现在已经给出计算代价的公式,问把多边形切成最多个不相交三角形的最小代价是多少。

    思路:首先判断多边形是否是凸多边形,之后就是区间dp了。

    求出凸包后,按逆时针来看。

    设置dp[i][j]为从顶点i到顶点j所围成凸多边形的最优解。

    枚举切点k (i < k < j)

    dp[i][j] = min(dp[i][k] + dp[k][j] + cost[i][k] + cost[k][j]);

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 310;
    struct point {
        int x,y;
        friend bool operator < (const point &a,const point &b) {
            if (a.y == b.y) return a.x < b.x;
            return a.y < b.y;
        }
    }src[MAXN];
    int cost[MAXN][MAXN];
    int N,P;
    int dp[MAXN][MAXN];
    
    point save[MAXN],tmp[MAXN];
    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);
    }
    
    int graphm(point * p,int n) {
        sort(p,p + n);
        save[0] = p[0];
        save[1] = p[1];
        int top = 1;
        for(int i = 0 ; i < n ; i++){
            while(top && cross(save[top],p[i],save[top-1]) >= 0)top--;
            save[++top] = p[i];
        }
    
        int mid = top;
        for(int i = n - 2 ; i >= 0 ; i--){
            while(top > mid && cross(save[top],p[i],save[top-1]) >= 0) top--;
            save[++top]=p[i];
        }
        return top;
    }
    
    int getcost(point a,point b) {
        return (abs(a.x + b.x) * abs(a.y+b.y)) % P;
    }
    
    int main() {
        while (scanf("%d%d",&N,&P) != EOF) {
            for (int i = 0 ; i < N ; i++) scanf("%d%d",&src[i].x,&src[i].y);
            int num = graphm(src,N);
            if (num < N) {
                printf("I can't cut.
    ");
            }
            else {
                memset(cost,0,sizeof(cost));
                for (int i = 0 ; i < N ; i++) {
                    for (int j = i + 2 ; j < N ; j++) cost[i][j] = cost[j][i] = getcost(save[i],save[j]);
                }
                memset(dp,0x3f,sizeof(dp));
                for (int i = 0 ; i < N ; i++) dp[i][(i + 1) % N] = 0;
                for (int d = 2 ; d <= N ; d++) {
                    for (int i = 0 ; i + d - 1 < N ; i++) {
                        int j = d + i - 1;
                        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
    ",dp[0][N - 1]);
            }
        }
        return 0;
    }
  • 相关阅读:
    RMQ Tarjan的Sparse-Table算法
    POJ3461一道kmp题,字符串Hash也可
    hdu3294 Manacher算法模板
    SQL复制数据表及表结构
    Delphi ResourceString的用法
    锐浪报表 Grid++Report 一维码无法固定条形码打印宽度
    Delphi中点击网页弹出的Alert对话框的确定按钮
    Delphi实现获取句柄并发送消息的方法(FindWindow、FindWindowEx、EnumChildWindows、SendMessage)
    Delphi 常用API 函数列表
    Delphi WinAPI 消息函数 SendMessage函数和 PostMessage的区别
  • 原文地址:https://www.cnblogs.com/Commence/p/5854688.html
Copyright © 2011-2022 走看看