zoukankan      html  css  js  c++  java
  • ZOJ 3735 Cake(区间DP,最优三角剖分)

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

    开始做下区间DP的题目了。

    题解可以参照大牛博客:http://blog.csdn.net/woshi250hua/article/details/7824433

    这题很经典,主要是思路:

    两种写法写的,一种是DP,一种是记忆化搜索。

    DP一定要注意循环的顺序。

    代码一:

    //============================================================================
    // Name        : ZOJ.cpp
    // Author      : 
    // Version     :
    // Copyright   : Your copyright notice
    // Description : Hello World in C++, Ansi-style
    //============================================================================
    
    #include <iostream>
    #include <stdio.h>
    #include <algorithm>
    #include <string.h>
    #include <math.h>
    using namespace std;
    const int MAXN=310;
    const int INF=0x3f3f3f3f;
    //二维凸包模板
    struct point
    {
        int x,y;
    };
    point list[MAXN];
    int stack[MAXN],top;
    
    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);
    }
    double dis(point p1,point p2)
    {
        return sqrt((double)(p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
    }
    bool cmp(point p1,point p2)
    {
        int tmp=cross(list[0],p1,p2);
        if(tmp>0)return true;
        else if(tmp==0&&dis(list[0],p1)<dis(list[0],p2))return true;
        else return false;
    }
    void init(int n)
    {
        int i,k;
        point p0;
        scanf("%d%d",&list[0].x,&list[0].y);
        p0.x=list[0].x;
        p0.y=list[0].y;
        k=0;
        for(i=1;i<n;i++)
        {
            scanf("%d%d",&list[i].x,&list[i].y);
            if((p0.y>list[i].y) || ((p0.y==list[i].y)&&(p0.x>list[i].x)))
            {
                p0.x=list[i].x;
                p0.y=list[i].y;
                k=i;
            }
        }
        list[k]=list[0];
        list[0]=p0;
        sort(list+1,list+n,cmp);
    }
    void graham(int n)
    {
        int i;
        if(n==1){top=0;stack[0]=0;}
        if(n==2)
        {
            top=1;
            stack[0]=0;
            stack[1]=1;
        }
        if(n>2)
        {
            for(i=0;i<=1;i++)stack[i]=i;
            top=1;
            for(i=2;i<n;i++)
            {
                while(top>0&&cross(list[stack[top-1]],list[stack[top]],list[i])<=0)top--;
                top++;
                stack[top]=i;
            }
        }
    }
    
    int n,m;
    int cost[MAXN][MAXN];
    int calc(point p1,point p2)//计算题目定义的cost
    {
        return abs(p1.x+p2.x)*abs(p1.y+p2.y)%m;
    }
    int dp[MAXN][MAXN];
    int main()
    {
    //    freopen("in.txt","r",stdin);
    //    freopen("out.txt","w",stdout);
        while(scanf("%d%d",&n,&m)==2)
        {
            init(n);
            graham(n);
            if(top!=n-1)
            {
                printf("I can't cut.\n");
                continue;
            }
            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]=calc(list[i],list[j]);
            for(int i=0;i<n;i++)
            {
                for(int j=i;j<n;j++)dp[i][j]=INF;
                dp[i][(i+1)%n]=0;
            }
            for(int i=n-3;i>=0;i--)
                for(int j=i+2;j<n;j++)
                    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\n",dp[0][n-1]);
        }
        return 0;
    }

    代码二:

    //============================================================================
    // Name        : ZOJ.cpp
    // Author      : 
    // Version     :
    // Copyright   : Your copyright notice
    // Description : Hello World in C++, Ansi-style
    //============================================================================
    
    #include <iostream>
    #include <stdio.h>
    #include <algorithm>
    #include <string.h>
    #include <math.h>
    using namespace std;
    const int MAXN=310;
    const int INF=0x3f3f3f3f;
    //二维凸包模板
    struct point
    {
        int x,y;
    };
    point list[MAXN];
    int stack[MAXN],top;
    
    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);
    }
    double dis(point p1,point p2)
    {
        return sqrt((double)(p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
    }
    bool cmp(point p1,point p2)
    {
        int tmp=cross(list[0],p1,p2);
        if(tmp>0)return true;
        else if(tmp==0&&dis(list[0],p1)<dis(list[0],p2))return true;
        else return false;
    }
    void init(int n)
    {
        int i,k;
        point p0;
        scanf("%d%d",&list[0].x,&list[0].y);
        p0.x=list[0].x;
        p0.y=list[0].y;
        k=0;
        for(i=1;i<n;i++)
        {
            scanf("%d%d",&list[i].x,&list[i].y);
            if((p0.y>list[i].y) || ((p0.y==list[i].y)&&(p0.x>list[i].x)))
            {
                p0.x=list[i].x;
                p0.y=list[i].y;
                k=i;
            }
        }
        list[k]=list[0];
        list[0]=p0;
        sort(list+1,list+n,cmp);
    }
    void graham(int n)
    {
        int i;
        if(n==1){top=0;stack[0]=0;}
        if(n==2)
        {
            top=1;
            stack[0]=0;
            stack[1]=1;
        }
        if(n>2)
        {
            for(i=0;i<=1;i++)stack[i]=i;
            top=1;
            for(i=2;i<n;i++)
            {
                while(top>0&&cross(list[stack[top-1]],list[stack[top]],list[i])<=0)top--;
                top++;
                stack[top]=i;
            }
        }
    }
    
    int n,m;
    int cost[MAXN][MAXN];
    int calc(point p1,point p2)//计算题目定义的cost
    {
        return abs(p1.x+p2.x)*abs(p1.y+p2.y)%m;
    }
    int dp[MAXN][MAXN];
    
    int solve(int s,int t)
    {
        if(dp[s][t]!=INF)return dp[s][t];
        int ans=INF;
        for(int i=s+1;i<t;i++)
            ans=min(ans,solve(s,i)+solve(i,t)+cost[s][i]+cost[i][t]);
        return dp[s][t]=ans;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        while(scanf("%d%d",&n,&m)==2)
        {
            init(n);
            graham(n);
            if(top!=n-1)
            {
                printf("I can't cut.\n");
                continue;
            }
            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]=calc(list[i],list[j]);
            for(int i=0;i<n;i++)
            {
                for(int j=i;j<n;j++)dp[i][j]=INF;
                dp[i][(i+1)%n]=0;
            }
            printf("%d\n",solve(0,n-1));
        }
        return 0;
    }
    人一我百!人十我万!永不放弃~~~怀着自信的心,去追逐梦想
  • 相关阅读:
    巧妇难为无米之炊( Model数据)
    jsp后台取出request请求头
    JSP本质的理解(浏览器调试,response里面的文本都是out.write写入网络流)
    【JZOJ6405】【NOIP2019模拟11.04】c
    【JZOJ6404】【NOIP2019模拟11.04】B
    【JZOJ6403】【NOIP2019模拟11.04】a
    【JZOJ6385】【NOIP2019模拟2019.10.23】B
    【JZOJ6379】【NOIP2019模拟2019.10.06】小w与密码(password)
    【JZOJ6373】【NOIP2019模拟2019.10.04】式神[八云蓝]
    【JZOJ6376】【NOIP2019模拟2019.10.05】樱符[完全墨染的樱花]
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3050401.html
Copyright © 2011-2022 走看看