hdu 3480 Division(斜率优化/四边形不等式)

题意:给你一堆数,让你组成m个集合,集合的价值是集合内元素的最大值与最小值的差的平方,求m个集合的价值总和最小

思路:

先给出TLE代码,斜率优化下次给出,转移方程dp[i][j]=min(dp[i][j],dp[i-1][k]+(a[j]-a[k+1])*(a[j]-a[k+1]));(ps:tzw竟然说买包烟十个人,九个人都会斜率优化过题,emmm)

#include <bits/stdc++.h>
using namespace std;
const int maxn=10005;
const int inf=0x3f3f3f3f;
int a[maxn],dp[maxn][maxn];
int que[maxn];
int n,m;

int main()
{
    int T;
    scanf("%d",&T);
    int cas=1;
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        sort(a+1,a+1+n);
        for(int i=0;i<=m;i++){
            for(int j=0;j<=n;j++){
                if(j==0)dp[i][j]=0;
                else dp[i][j]=inf;
            }
        }
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++){
                for(int k=0;k<j;k++){
                    dp[i][j]=min(dp[i][j],dp[i-1][k]+(a[j]-a[k+1])*(a[j]-a[k+1]));
//                    printf("test %d dp[%d][%d] == %d\n",k,i,j,dp[i][j]);
                }
            }
        }
//        for(int i=0;i<=m;i++){
//            for(int j=0;j<=n;j++){
//                printf("%d ",dp[i][j]);
//            }
//            puts("");
//        }
        printf("Case %d: %d\n",cas++,dp[m][n]);
    }
    return 0;
}

 已补,代码参照http://blog.sina.com.cn/s/blog_6e63f59e0101aeaf.html

不知道为什么对于二维的斜率优化,写成相除的形式就跑不出样例,感觉在vj上交的没有什么错,只用了slop函数,没有什么其他特别的地方

-----手动分割------------

这里是四边形不等式优化,最近才对四边形不等式有所突破

主要得益于赵爽的《动态规划加速原理 之四边形不等式》

窝觉得论文写得还是很容易懂的,只要能认真看,以及手动进行数学证明,结合网上的题解,对于四边形不等式的优化的理解应该是没什么问题的

最近几天把黑书补一下

然后尽量多刷一下四边形优化的题,斜率优化已经懂了许多了

附上四边形代码(说实话,我不是很懂初始化,可能需要手动推算一下,还是懒):

#include <bits/stdc++.h>
using namespace std;
const int maxn=100007;
const int inf=0x3f3f3f3f;
int n,m,ans,T;
int a[10005],dp[5005][10005],s[5005][10005];

int main()
{
    scanf("%d",&T);
    int cas=1;
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        sort(a+1,a+1+n);
        memset(dp,0x3f,sizeof(dp));
        for(int i=0;i<=m;i++){
            dp[i][i]=0;
            s[i][i]=i;
        }
        for(int i=m+1;i<=n;i++){
            s[m+1][i]=i;
        }
        for(int len=1;len<n;len++){
            for(int i=1;i<=m;i++){
                int j=len+i;
                if(j>n)break;
                for(int k=s[i][j-1];k<=s[i+1][j];k++){
                    int t=dp[i-1][k-1]+(a[k]-a[j])*(a[k]-a[j]);
                    if(dp[i][j]>t){
                        dp[i][j]=t; s[i][j]=k;
                    }
                }
            }
        }

        printf("Case %d: %d\n",cas++,dp[m][n]);
    }
    return 0;
}

 

posted @ 2018-03-09 15:39  啦啦啦天啦噜  阅读(148)  评论(0编辑  收藏  举报