zoukankan      html  css  js  c++  java
  • ZOJ3537 Cake(区间dp+凸包判断)

    网上很多区间dp的代码是记忆化搜索的,还有些说这种区间dp必须倒序枚举

    其实没有必要倒序,我们只需要按正常的区间dp的定义,第一维是长度,第二维枚举起点,第三维枚举断点即可

    判断凸包的方法就是跟网上一样的常用方法Graham

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn = 1005;
    const int inf = 1000000000;
    
    struct node {
        int x, y;
    } p[maxn], save[maxn], tmp[maxn];
    int cost[maxn][maxn], n, m;
    int dp[maxn][maxn];
    
    int dis(node p1, node p2, node p0) {
        return (p1.x-p0.x) * (p2.y-p0.y) - (p2.x-p0.x) * (p1.y-p0.y);  
    }
    
    bool cmp(const node &a, const node &b) {
        if (a.y == b.y) return a.x < b.x;
        return a.y < b.y;
    }
    
    int Graham(node *p,int n) {  
        sort(p,p + n,cmp);  
        save[0] = p[0];  
        save[1] = p[1];  
        int top = 1;  
        for (int i = 0;i < n; i++) {  
            while (top && dis(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 && dis(save[top],p[i],save[top-1])>=0) top--;  
            save[++top]=p[i];  
        }  
        return top;  
    }  
    
    int Count(node a, node b) {
        return (abs(a.x+b.x) * abs(a.y+b.y)) % m;
    }
    
    int main() {
        while (scanf("%d%d",&n,&m) != EOF) {  
            for (int i = 0; i < n; ++i)  
                scanf("%d%d",&p[i].x,&p[i].y);  
    
            int tot = Graham(p,n);  //求凸包  
            if (tot != 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] =(abs(save[i].x+save[j].x) * abs(save[i].y+save[j].y)) % m;  
    
                memset(dp,0x3f,sizeof dp);
                for(int i=0;i<n;i++)
                dp[i][i+1]=0;
                int len,l,r,k;
            for(len=3;len<=n;len++){
                for(l=0;l+len-1<n;l++){
                    r=l+len-1;
                    for(k=l+1;k<r;k++){
                        dp[l][r]=min(dp[l][r],dp[l][k]+dp[k][r]+cost[l][k]+cost[k][r]);
                    }
                }
            }
                printf("%d
    ",dp[0][n-1]);  
            }  
        }  
        return 0;
    }
    View Code
  • 相关阅读:
    7zip 自解压安装程序
    修改当前启动菜单项的HyperVisorLaunchType
    VMware 虚拟镜像转 Hyper-V(Win10/2016)
    旋转基础知识
    变换及移动基础知识
    文字及排版章末小结
    文字排版相关
    文字变形及封套扭曲
    LinQ学习笔记.
    PHP笔记-PHP中Web Service.
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12335231.html
Copyright © 2011-2022 走看看