Lawrence HDU - 2829 斜率dp

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAX = 1000+10;
//dp[i][j]:把前 i 个数分成 j 段后能得到的序列的最小权值和
//dp[i][j] = min( dp[k][j-1] + cost[i] - cost[k] - sum[k] *(sum[i] - sum[k]) ) ;
//sum[i]*sum[k] + dp[i][j] - cost[i] = dp[k][j-1] - cost[k] + sum[k]*sum[k] ;
long long a[MAX];
long long sum[MAX],cost[MAX];
long long q[MAX];
long long dp[MAX][MAX];
long long up(int j,int k1,int k2) {
    return ((dp[k1][j-1]-cost[k1]+sum[k1]*sum[k1])-(dp[k2][j-1]-cost[k2]+sum[k2]*sum[k2]));
}
long long down(int k1,int k2) {
    return (sum[k1]-sum[k2]);
}
int main() {
    int n,m;
    while(scanf("%d%d",&n,&m),n||m) {
        for(int i=1; i<=n; i++)
            scanf("%d",&a[i]);
        sum[0]=0;
        cost[0]=0;
        for(int i=1; i<=n; i++) {
            sum[i]=sum[i-1]+a[i];
            cost[i]=cost[i-1]+sum[i-1]*a[i];
        }
        memset(dp,0,sizeof(dp));
        //处理边界
        for(int i=1; i<=n; i++) {
            dp[i][0]=cost[i];
            dp[i][i-1]=0;
        }
        for(int j=1; j<=m; j++) {
            int l=0;
            int r=0;
            q[0]=j;
            for(int i=j+1; i<=n; i++) {
                while(l<r&&up(j,q[l+1],q[l])<=sum[i]*down(q[l+1],q[l]))
                    l++;
                int k=q[l];
                dp[i][j]=dp[k][j-1]+cost[i]-cost[k]-sum[k]*(sum[i]-sum[k]);
                while(l<r&&up(j,q[r],q[r-1])*down(i,q[r])>=up(j,i,q[r])*down(q[r],q[r-1]))
                    r--;
                q[++r]=i;
            }
        }
        printf("%lld\n",dp[n][m]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12513187.html

时间: 2024-10-29 08:18:55

Lawrence HDU - 2829 斜率dp的相关文章

hdu 3507 斜率dp

不好理解,先多做几个再看 此题是很基础的斜率DP的入门题. 题意很清楚,就是输出序列a[n],每连续输出的费用是连续输出的数字和的平方加上常数M 让我们求这个费用的最小值. 设dp[i]表示输出前i个的最小费用,那么有如下的DP方程: dp[i]= min{ dp[j]+(sum[i]-sum[j])^2 +M }  0<j<i 其中 sum[i]表示数字的前i项和. 相信都能理解上面的方程. 直接求解上面的方程的话复杂度是O(n^2) 对于500000的规模显然是超时的.下面讲解下如何用斜率

HDU 3480 斜率dp

Division Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 999999/400000 K (Java/Others)Total Submission(s): 5053    Accepted Submission(s): 1980 Problem Description Little D is really interested in the theorem of sets recently. There’s a prob

HDU 2829 Lawrence (斜率DP)

斜率DP 设dp[i][j]表示前i点,炸掉j条边的最小值.j<i dp[i][j]=min{dp[k][j-1]+cost[k+1][i]} 又由得出cost[1][i]=cost[1][k]+cost[k+1][i]+sum[k]*(sum[i]-sum[k]) cost[k+1][i]=cost[1][i]-cost[1][k]-sum[k]*(sum[i]-sum[k]) 代入DP方程 可以得出 y=dp[k][j-1]-cost[1][k]+sum[k]^2 x=sum[k]. 斜率s

HDU 2829 Lawrence(动态规划-四边形不等式)

Lawrence Problem Description T. E. Lawrence was a controversial figure during World War I. He was a British officer who served in the Arabian theater and led a group of Arab nationals in guerilla strikes against the Ottoman Empire. His primary target

HDU 2993 MAX Average Problem(斜率DP经典+输入输出外挂)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2993 题目大意:给出n,k,给定一个长度为n的序列,从其中找连续的长度大于等于k的子序列使得子序列中的平均值最小. 解题思路:斜率DP经典题, 详细分析见: NOI2004年周源的论文<浅谈数形结合思想在信息学竞赛中的应用> 还有要注意要用输入输出外挂,不是getchar()版的,是fread()版的,第一次遇到这么变态的题目- -|||. 代码: 1 #include<iostream&g

HDU 3480 - Division - [斜率DP]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3480 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 999999/400000 K (Java/Others) Little D is really interested in the theorem of sets recently. There's a problem that confused him a long time.   

HDU 3507 Print Article(斜率DP优化)

Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique, he still like to use it to print articles. But it is too old to work for a long time and it will certainly wear and tear, so Zero use a cost to evaluate t

「kuangbin带你飞」专题二十 斜率DP

layout: post title: 「kuangbin带你飞」专题二十 斜率DP author: "luowentaoaa" catalog: true tags: mathjax: true - kuangbin - 动态规划 - 斜率DP 传送门 A.HDU - 3507 Print Article 题意 就是输出序列a[n],每连续输出的费用是连续输出的数字和的平方加上常数M 让我们求这个费用的最小值. 题解 概率DP的入门题,把我搞得要死要活的. 首先dp[i]表示输出前i

hdu 4734 数位dp

http://acm.hdu.edu.cn/showproblem.php?pid=4734 Problem Description For a decimal number x with n digits (AnAn-1An-2 ... A2A1), we define its weight as F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1. Now you are given two numbers A and B, plea