zoukankan      html  css  js  c++  java
  • HDOJ 3516 Tree Construction 四边形优化dp

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=3516

    题意:

    大概就是给你个下凸包的左侧,然后让你用平行于坐标轴的线段构造一棵树,并且这棵树的总曼哈顿距离最短

    题解:

    很容易得到转移方程:

    $$dp[i][j]=min { dp[i][k-1]+dp[k][j] + dis(uni(i,k-1),uni(k,j))}$$

    其中$dp[i][j]$表示从$i$到$j$的最优解,$dis(i,j)$表示$i$和$j$之间的曼哈顿距离,$uni(i,j)$表示将$i$和$j$用平行于坐标轴的线段连在一起时的拐角点。

    然后可以证明这是满足四边形优化条件的。

    然后四边形优化一下就好。

    代码:

    #include<iostream>
    #include<cstring>
    #include<queue>
    #include<vector>
    #include<algorithm>
    #include<climits>
    #include<cmath>
    #define MAX_N 1234
    #define INF LLONG_MAX/1234
    using namespace std;
    
    typedef long long LL;
    
    LL dp[MAX_N][MAX_N];
    
    int n;
    
    struct point {
    public:
        LL x, y;
    
        point(LL xx, LL yy) : x(xx), y(yy) { }
    
        point() { }
    };
    
    point P[MAX_N];
    
    LL dis(point a,point b){
        return abs(a.x-b.x)+abs(a.y-b.y);
    }
    
    point uni(point a,point b) {
        return point(min(a.x, b.x), min(a.y, b.y));
    }
    
    int s[MAX_N][MAX_N];
    
    int main() {
        cin.sync_with_stdio(false);
        while (cin >> n) {
            for (int i = 1; i <= n; i++)
                cin >> P[i].x >> P[i].y;
            for (int i = 0; i <= n; i++)
                for (int j = 0; j <= n; j++) {
                    if (i == j)
                        dp[i][j] = 0;
                    else
                        dp[i][j] = INF;
                }
            for (int i = 1; i < n; i++)
                dp[i][i + 1] = dis(P[i], P[i + 1]), s[i][i + 1] = i + 1;
            for (int t = 2; t <= n; t++)
                for (int i = 1; i + t <= n; i++) {
                    int j = i + t;
                    int pos = 0;
                    for (int k = s[i][j - 1]; k <= s[i + 1][j]; k++)
                        if (dp[i][j] > dp[i][k - 1] + dp[k][j]+ dis(uni(P[i], P[k - 1]), uni(P[k], P[j])))
                            dp[i][j] = dp[i][k - 1] + dp[k][j] + dis(uni(P[i], P[k - 1]), uni(P[k], P[j])), pos = k;
                    s[i][j] = pos;
                }
            cout << dp[1][n] << endl;
        }
        return 0;
    }
  • 相关阅读:
    个人便签
    秒杀系统架构分析与实战
    NPOI大数据分批写入同个Excel
    js获取鼠标坐标位置兼容多个浏览器
    月薪3万的程序员都避开了哪些坑
    怎样理解阻塞非阻塞与同步异步的区别?
    JS中的prototype
    互联网——降级论
    fedora自带OpenJDK,所以如果安装官方的JDK的话要先删除OpenJDK
    cygwin 安装完后不能进入think问题,网上99%都是错误的
  • 原文地址:https://www.cnblogs.com/HarryGuo2012/p/4860581.html
Copyright © 2011-2022 走看看