• 斜率优化板题 HDU2829 Lawrence


    • 题目大意:给定一个长度为nn的序列,至多将序列分成m+1m+1段,每段序列都有权值,权值为序列内两个数两两相乘之和。求序列权值和最小为多少?
    • 数据规模:m<=n<=1000.m<=n<=1000.
    • 分析:令w[i,j]w[i,j]表示区间[i,j][i,j]中两两乘积之和,f[i][j]f[i][j]表示前jj个数分成ii段的最小值。
      f[i][j]=f[i1][k]+w[k+1,j]f[i][j]=f[i-1][k]+w[k+1,j]
      w[k+1,j]w[k+1,j]可以转换为w[1,j]w[1,k]sum[k](sum[j]sum[k])w[1,j]-w[1,k]-sum[k]*(sum[j]-sum[k])
      其中sum[j]sum[j]表示前j个数的前缀和。令w[i]=w[1,i]w[i]=w[1,i]
      f[i][j]=f[i1][k]+w[j]w[k]sum[k](sum[j]sum[k])f[i][j]=f[i-1][k]+w[j]-w[k]-sum[k]*(sum[j]-sum[k])
      y=f[i1][k]w[k]+sum[k]2y=f[i-1][k]-w[k]+sum[k]^2
      x=sum[k]x=sum[k]
      k=sum[j]k=sum[j]
      g=f[i][j]w[j]g=f[i][j]-w[j]
      则有:ykx=by-kx=b
      此为直线方程,kk为定值,要求bb(w[j]w[j]为定值)最小,即为直线的截距最小。平面上有若干点(x,y)(x,y),这些点是由各个决策点产生的。而将直线从下往上平移,它接触到的第一个点即为最佳决策点。因为斜率bb是上升的,所以,下一阶段的直线方程斜率更高,于是最佳决策点一定形成了下凸包序列。
      还可以用滚动数组…具体见代码:
    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1005;
    #define LL long long
    int n, m, s, t, dq[MAXN];
    LL sum[MAXN], w[MAXN], f[2][MAXN];
    
    inline LL Getup(int now, int i, int j) { return (f[now][i] + sum[i]*sum[i] - w[i]) - (f[now][j] + sum[j]*sum[j] - w[j]); }//Yi-Yj
    inline LL Getdown(int now, int i, int j) { return sum[i] - sum[j]; }//Xi-Xj
    
    int main ()
    {
    	int x;
    	while(scanf("%d%d", &n, &m), n || m)
    	{
    		for(int i = 1; i <= n; i++)
    			scanf("%d", &x), sum[i] = sum[i-1] + x, w[i] = w[i-1] + sum[i-1] * x;
    		int now = 0;
    		for(int i = 1; i <= n; i++) f[now][i] = w[i];
    		for(int i = 2; i <= m+1; i++)
    		{
    			now ^= 1, s = t = 0, dq[t++] = 0;
    			for(int j = 1; j <= n; j++)
    			{
    				while(t-s > 1 && Getup(now^1, dq[s+1], dq[s])  <= sum[j] * Getdown(now^1, dq[s+1], dq[s])) s++;
    				f[now][j] = f[now^1][dq[s]] + w[j] - w[dq[s]] - sum[dq[s]] * (sum[j] - sum[dq[s]]);
    				while(t-s > 1 && Getup(now^1, j, dq[t-1]) * Getdown(now^1, dq[t-1], dq[t-2]) <= Getup(now^1, dq[t-1], dq[t-2]) * Getdown(now^1, j, dq[t-1])) t--;
    				dq[t++] = j;
    			}
    		}
    		printf("%lld
    ", f[now][n]);
    	}
    }
    
  • 相关阅读:
    sql server 2008 64位连接sql 2000服务器的时候出现
    MySQL忘记密码怎么修改密码
    vs2015 行数统计
    javascript和c#aes加密方法互解
    vs2015 不能启动 iis express
    修改oracle的字符集操作方法
    PL/SQL Developer连接本地Oracle 11g 64位数据库
    CodeSmith Generator 7.0.2激活步骤
    PetaPoco利用ODP.NET Managed Driver连接Oracle
    解决Chrome插件安装时出现的“程序包无效”问题亲测可用
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039477.html
Copyright © 2020-2023  润新知