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
  • 相关阅读:
    杭电 Problem
    杭电Problem 5053 the sum of cube 【数学公式】
    杭电 Problem 2089 不要62 【打表】
    杭电 Problem 4548 美素数【打表】
    杭电 Problem 2008 分拆素数和 【打表】
    杭电 Problem 1722 Cake 【gcd】
    杭电 Problem 2187 悼念512汶川大地震遇难同胞——老人是真饿了【贪心】
    杭电Problem 1872 稳定排序
    杭电 Problem 1753 大明A+B
    东北林业大 564 汉诺塔
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12335231.html
Copyright © 2011-2022 走看看