【四边形】 HDU 3516 Tree Construction

通道

题意:二维坐标上的点,建一个长度和最小的树包含全部点

思路:

定义状态 dp[i,j]表示点i到点j合并在一起的最小花费(树枝的长度),
状态转移方程:dp[i,j]= min(dp[i,k]+dp[k+1,j]+cost(i,j) ) i<k<j
cost(i,j)=py[k]-py[j]+px[k+1]-px[i];
当j固定时,cost(i,j)单调递减函数
我们猜测cost(i,j)满足四边形不等式
证明: F(i)=cost(i,j+1)-cost(i,j)=py[j]-py[j+1]是一个与i无关的多项式,
所以j固定时,F(i)满足四边形不等式,得证。
s[i,j]=k;s[i-1,j] <= s[i,j] <= s[i,j+1];
由于决策s具有单调性,因此状态转移方程可修改为:


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[1010][1010];
int s[1010][1010];
int main(){
    int n;
    int x[1010];
    int y[1010];
    while(scanf("%d",&n)!=EOF){
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++){
            scanf("%d%d",&x[i],&y[i]);
            s[i][i]=i;
        }
        for(int ln=2;ln<=n;ln++){
            for(int i=1;i<=n-ln+1;i++){
                dp[i][i+ln-1]=999999;
                for(int j=s[i][i+ln-2];j<=s[i+1][i+ln-1];j++){
                    if(dp[i][i+ln-1]>dp[i][j]+dp[j+1][i+ln-1]+abs(x[j+1]-x[i])+abs(y[i+ln-1]-y[j])){
                        dp[i][i+ln-1]=dp[i][j]+dp[j+1][i+ln-1]+abs(x[j+1]-x[i])+abs(y[i+ln-1]-y[j]);
                        s[i][i+ln-1]=j;
                    }
                }
            }
        }
        printf("%d\n",dp[1][n]);
    }
    return 0;
}

时间: 2024-10-10 11:48:27

【四边形】 HDU 3516 Tree Construction的相关文章

HDU 3516 Tree Construction

区间$dp$,四边形优化. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue

HDOJ 3516 Tree Construction

四边形优化DP Tree Construction Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 868    Accepted Submission(s): 470 Problem Description Consider a two-dimensional space with a set of points (xi, yi) t

HDU 3516 DP 四边形不等式优化 Tree Construction

设d(i, j)为连通第i个点到第j个点的树的最小长度,则有状态转移方程: d(i, j) = min{ d(i, k) + d(k + 1, j) + p[k].y - p[j].y + p[k+1].x - p[i].x } 然后用四边形不等式优化之.. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <

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

【HDU】3516 Tree Construction

http://acm.hdu.edu.cn/showproblem.php?pid=3516 题意:平面n个点且满足xi<xj, yi>yj, i<j.xi,yi均为整数.求一棵树边只能向上和向右延展的经过所有点的最小长度.(n<=1000, 0<=xi, yi<=10000) #include <cstdio> using namespace std; const int N=1005, oo=~0u>>1; int d[N][N], x[N]

hdu 5293 Tree chain problem(树链剖分+树形dp)

题目链接:hdu 5293 Tree chain problem 维护dp[u], sum[u],dp[u]表示以u为根节点的子树的最优值.sum[u]表示以u节点的所有子节点的dp[v]之和.对于边a,b,w,在LCA(a,b)节点的时候进行考虑.dp[u] = min{dp[u], Sum(a,b) - Dp(a,b) + sum[u] | (ab链上的点,不包括u } #pragma comment(linker, "/STACK:1024000000,1024000000")

hdu 5370 Tree Maker(catalan+dp)

题目链接:hdu 5370 Tree Maker n个节点的二叉树种类为Catalan数的第n项 对于一棵子树而言,被移动过的节点就是确定的位置,所以只要知道已经确定位置的K个节点有多少个空孩子指针M,和就该子树下的N个未确定位置的节点,等于是说用N个节点构造M个可为空的子树的种类数.对于整个树的形态数即为若干棵独立的子树形态数的乘积. 定义dp[i][j]为用i个节点构造j棵树的形态数,dp[i][j] = sum{ dp[i-1][j-k] * catalan[k] | 0 ≤ k ≤j }

HDU 5044 Tree(树链剖分)

HDU 5044 Tree 题目链接 就简单的树链剖分,不过坑要加输入外挂,还要手动扩栈 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int N = 100005; #pragma comment(linker, "/STACK:1024000000,1024000000"

hdu 4757 Tree(可持久化字典树)

题目链接:hdu 4757 Tree 题目大意:给定一棵树,每一个节点有一个值.如今有Q次询问,每次询问u到v路径上节点值与w亦或值的最大值. 解题思路:刚開始以为是树链剖分,事实上树链剖分仅仅是用来求LCA(能够不用树链剖分). 可持久化字典树.在每次插入的同一时候,不改动原先的节点.而是对全部改动的节点复制一个新的节点,而且在新的节点 上做操作,这样做的目的是可以获取某次改动前的状态.同过可持久化的操作,保留了改动前后的公共数据. 对给定树上的全部节点权值建立01字典树,然后每一个节点都保存