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

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3537

    题目大意:给出一些点表示多边形顶点的位置,如果不是凸多边形(凸包)则不能切,直接输出"I can't cut."
    切多边形时每次只能在顶点和顶点间切,每切一次的花费为 cost(i, j) = |xi + xj| * |yi + yj| % p。
    问把多边形切成最多个不相交三角形的最小代价是多少。

    解题思路:先求出凸包,接着可以用区间DP解决,设dp[i][j]为以i为起点,j为终点的凸包被切成三角形的最小花费。
    那么可以得到状态转移方程:dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+cost[i][k]+cost[k][j])。
    不懂的可以看下图(非原创):

    代码:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<vector>
      5 #include<cmath>
      6 #include<algorithm>
      7 using namespace std;
      8 const int INF=0x3f3f3f3f;
      9 const int N=505;
     10 const double eps = 1e-9;
     11 
     12 int n,mod;
     13 int dp[N][N],cost[N][N];
     14 
     15 struct P
     16 {
     17     double x, y;
     18     P(double x=0, double y=0):x(x), y(y) {}
     19     double add(double a, double b){
     20         if(fabs(a+b)<eps*(fabs(a)+fabs(b))) return 0;
     21         return a+b;
     22     }
     23     P operator + (P p){
     24         return P(add(x, p.x), add(y, p.y));
     25     }
     26     P operator - (P p){
     27         return P(add(x, -p.x), add(y, -p.y));
     28     }
     29     P operator *(double d){
     30         return P(x*d, y*d);
     31     }
     32     double dot(P p){                 //点积
     33         return add(x*p.x, y*p.y);
     34     }
     35     double det(P p){                 //差积
     36         return add(x*p.y, -y*p.x);
     37     }
     38 }ps[N];
     39 
     40 double dist(P a, P b){
     41     return sqrt((b-a).dot(b-a));
     42 }
     43 
     44 bool cmp_x(const P& p, const P& q){
     45     if(p.x!=q.x) return p.x < q.x;
     46     return p.y < q.y;
     47 }
     48 
     49 vector<P> convex_hull(P *ps, int n){
     50     sort(ps,ps+n,cmp_x);
     51     int k = 0;          //凸包顶点数
     52     vector<P> qs(n*2);
     53     //构造凸包的下侧
     54     for(int i=0; i<n; i++)
     55     {
     56         while(k>1 && (qs[k-1]-qs[k-2]).det(ps[i]-qs[k-1])<=0) k--;
     57         qs[k++] = ps[i];
     58     }
     59     //构造凸包的上侧
     60     for(int i=n-2,t=k; i>=0; i--)
     61     {
     62         while(k>t && (qs[k-1]-qs[k-2]).det(ps[i]-qs[k-1])<=0) k--;
     63         qs[k++] = ps[i];
     64     }
     65     qs.resize(k-1);
     66     return qs;
     67 }
     68 
     69 int getcost(P p1,P p2){
     70     return abs((int)p1.x+(int)p2.x)*abs((int)p1.y+(int)p2.y)%mod;
     71 }
     72 
     73 int main(){
     74     while(~scanf("%d%d",&n,&mod)){
     75         for(int i=0;i<n;i++){
     76             scanf("%lf%lf",&ps[i].x,&ps[i].y);
     77         }
     78         vector<P>tp;
     79         tp=convex_hull(ps,n);
     80         if(tp.size()<n){
     81             puts("I can't cut.");
     82             continue;
     83         }
     84         //注意,用获得的凸包做DP,即使用tp做DP,保证凸包上的点的顺序
     85         memset(cost,0,sizeof(cost));
     86         memset(dp,0,sizeof(dp));
     87         for(int i=0;i<n;i++){
     88             for(int j=i+2;j<n;j++){
     89                 cost[i][j]=getcost(tp[i],tp[j]);
     90             }
     91         }
     92         for(int len=3;len<n;len++){
     93             for(int i=0;i+len<n;i++){
     94                 int j=i+len;
     95                 dp[i][j]=INF;
     96                 for(int k=i+1;k<=j-1;k++){
     97                     dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+cost[i][k]+cost[k][j]);
     98                 }
     99             }
    100         }
    101         printf("%d
    ",dp[0][n-1]);
    102     }
    103     return 0;
    104 }
  • 相关阅读:
    jquery笔记
    JavaScript 运动框架 Step by step(转)
    js中获取页面元素方法总结
    图片缩放效果IE和火狐兼容模式
    js循环运动效果实现
    网页捕捉错误
    (图文介绍)Virtualbox下实现Ubuntu虚拟机和win7主机文件共享(很简单,亲自试用,按此步骤一般都会成功)
    FFT算法实现(fft算法)快速傅里叶变换算法实现
    $_SESSION跨页面问题
    暂别ACM,转移阵地
  • 原文地址:https://www.cnblogs.com/fu3638/p/8809003.html
Copyright © 2011-2022 走看看