• HDU.3516.Tree Construction(DP 四边形不等式)


    题目链接

    贴个教程: 四边形不等式学习笔记

    (Description)

    给出平面上的(n)个点,满足(X_i)严格单增,(Y_i)严格单减。以(x)轴和(y)轴正方向作边,使这(n)个点构成一棵树,最小化树边边的总长。

    (Solution)

    考虑有两棵构造好的树,要合并这两棵树,要从右边的树中找一个最优点连到左边的树上
    不难想到区间DP(真的想不到==)
    (f[i][j])表示将([i,j])合并为一棵树的最小代价,那么有 (f[i][j] = min{ f[i][k-1]+f[k][j]+cost(i,j,k) })
    (cost(i,j,k)=X[k]-X[i]+Y[k-1]-Y[j]) //ps: 当前左边树主干在 (Xi) 位置,且下部高度为 (Y_{k-1}),合并后下部应为 (Yj);另外肯定是拿右边树的最左上点合并啊
    这个(cost)是三维的,证不了(cost)满足四边形不等式
    那想下 决策应该是满足单调性的,即 (P[i][j-1]leq P[i][j]leq P[i+1][j])
    注意左端点应是(max(P[i][j-1],i+1))
    (f)应该满足四边形不等式,不会证。

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    #define gc() getchar()
    const int N=1005;
    
    int n,X[N],Y[N],P[N][N],f[N][N];
    
    inline int read()
    {
    	int now=0,f=1;register char c=gc();
    	for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now*f;
    }
    
    int main()
    {
    	while(~scanf("%d",&n))
    	{
    		for(int i=1; i<=n; ++i) X[i]=read(),Y[i]=read();
    		memset(f,0x3f,sizeof f);
    		for(int i=1; i<=n; ++i) P[i][i]=i, f[i][i]=0;
    		for(int tmp,i=n-1; i; --i)
    			for(int j=i+1; j<=n; ++j)
    				for(int k=std::max(P[i][j-1],i+1); k<=P[i+1][j]; ++k)
    					if(f[i][j]>(tmp=f[i][k-1]+f[k][j]+X[k]-X[i]+Y[k-1]-Y[j]))
    						f[i][j]=tmp, P[i][j]=k;
    		printf("%d
    ",f[1][n]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    CCF CSP 题解
    CCF CSP 2019032 二十四点
    CCF CSP 2018121 小明上学
    CCF CSP 2019092 小明种苹果(续)
    CCF CSP 2019091 小明种苹果
    CCF CSP 2019121 报数
    CCF CSP 2019031 小中大
    CCF CSP 2020061 线性分类器
    CCF CSP 2020062 稀疏向量
    利用国家气象局的webservice查询天气预报(转载)
  • 原文地址:https://www.cnblogs.com/SovietPower/p/8459574.html
Copyright © 2020-2023  润新知