hdu 2829 Lawrence (dp斜率优化||四边形优化)
来源:互联网 发布:阿里云架设游戏教程 编辑:程序博客网 时间:2024/06/05 20:47
题意:
给出很多一段路线,由n个点组成,每个点有价值,定义某个区间[i,j]上的价值为这个区间没两个点两两相乘的和,现在可以选择m个点炸掉,这样可以分成m+1段,总的价值就是每段价值的和。那么现在问题来了,如何分段使得价值对低呢?
题解:
这题可以用队列优化和四边形优化,首先讲下队列优化的。
队列优化:
方程先写出来 设dp[i][j]表示前j点,炸掉i条边的最小值。j>i
状态方程: dp[i][j]=min{dp[i-1][k]+w[k+1][j]}
观察没发现任何的单调性。那么变形一下
又由得出
w[1][j]=w[1][k]+w[k+1][j]+s[k]*(s[j]-s[k])
将
w[k+1][j]=w[1][j]-w[1][k]-s[k]*(s[j]-s[k])
代入DP方程
可以得出 y=dp[i-1][k]-w[1][k]+s[k]^2
x=s[k].
斜率s[j]
那么现在就可以用斜率优化了。
#include<iostream>#include<math.h>#include<stdio.h>#include<algorithm>#include<string.h>#include<vector>#include<map>using namespace std;typedef __int64 lld;#define oo 0x3f3f3f3f#define maxn 1005int dp[maxn][maxn];int q[maxn];int w[maxn],s[maxn];int main(){ int n,m,a,head,tail; while(scanf("%d %d",&n,&m)!=EOF) { if(n==0&&m==0)break; w[0]=s[0]=0; for(int i=1;i<=n;i++) { scanf("%d",&a); s[i]=s[i-1]+a; w[i]=w[i-1]+s[i-1]*a; } for(int i=1;i<=n;i++) { dp[0][i]=w[i]; dp[i-1][i]=0; } for(int i=1;i<=m;i++) { head=tail=0; q[tail++]=i; for(int j=i+1;j<=n;j++) { while(head+1<tail) { int k1=q[head]; int k2=q[head+1]; int x1=s[k1]; int x2=s[k2]; int y1=dp[i-1][k1]-w[k1]+s[k1]*s[k1]; int y2=dp[i-1][k2]-w[k2]+s[k2]*s[k2]; if((y2-y1)<=(x2-x1)*s[j]) head++; else break; } int k=q[head]; dp[i][j]=dp[i-1][k]+w[j]-w[k]-s[k]*(s[j]-s[k]); while(head+1<tail) { int k1=q[tail-2]; int k2=q[tail-1]; int k3=j; int x1=s[k1]; int x2=s[k2]; int x3=s[k3]; int y1=dp[i-1][k1]-w[k1]+s[k1]*s[k1]; int y2=dp[i-1][k2]-w[k2]+s[k2]*s[k2]; int y3=dp[i-1][k3]-w[k3]+s[k3]*s[k3]; if((y3-y2)*(x2-x1)<=(y2-y1)*(x3-x2)) tail--; else break; } q[tail++]=j; } } printf("%d\n",dp[m][n]); } return 0;}
那么现在讲下四边形优化
四边形优化:
方程: dp[i][j]=min{dp[i-1][k]+w[k+1][j]}
像这样 f[i][j] = min{ f[i-1][j] + f[i+1][j] } 形式的方程都可以用四边形优化,证明?胡策,没几个人会证,不过这样形几乎是可以用四边形优化的
那么我们设一个优化的标记mark[i][j]表示最大能达到的
#include<iostream>#include<math.h>#include<stdio.h>#include<algorithm>#include<string.h>#include<vector>#include<map>using namespace std;typedef __int64 lld;#define oo 0x3f3f3f3f#define maxn 1005lld dp[maxn][maxn];int mark[maxn][maxn];lld w[maxn][maxn],val[maxn],sum[maxn][maxn];void getw(int n){ for(int i=1;i<=n;i++) { sum[i][i]=0; for(int j=i+1;j<=n;j++) sum[i][j]=sum[i][j-1]+val[i]*val[j]; } w[n][n]=0; for(int i=n-1;i>=1;i--) { for(int j=i+1;j<=n;j++) w[i][j]=w[i+1][j]+sum[i][j]; }}void inst(int n){ memset(dp,0x3f,sizeof dp); for(int i=1;i<=n;i++) { dp[1][i]=w[1][i]; mark[1][i]=0; }}void Dp(int n,int m){ inst(n); for(int i=2;i<=m+1;i++) { mark[i][n+1]=n; for(int j=n;j>=i;j--) for(int k=mark[i-1][j];k<=mark[i][j+1];k++) if(dp[i][j]>dp[i-1][k]+w[k+1][j]) { dp[i][j]=dp[i-1][k]+w[k+1][j]; mark[i][j]=k; } }}int main(){ int n,m; while(scanf("%d %d",&n,&m)!=EOF) { if(n==0&&m==0)break; for(int i=1;i<=n;i++) scanf("%I64d",&val[i]); getw(n);//精髓所在,得到两两点区间的权值 Dp(n,m);//状态转移 if(m+1>n-1) dp[m+1][n]=0; printf("%I64d\n",dp[m+1][n]); } return 0;}
0 0
- HDU 2829 Lawrence(四边形优化dp/斜率优化dp)
- Hdu 2829 Lawrence(dp+四边形优化或斜率优化)
- hdu 2829 Lawrence (dp斜率优化||四边形优化)
- HDU-2829 Lawrence 【斜率优化DP】【四边形不等式优化】
- HDU-2829 Lawrence 四边形优化DP 斜率优化
- Lawrence - HDU 2829斜率优化,四边形不等式优化
- hdu 2829 Lawrence 四边形优化 dp
- HDU 2829 Lawrence【dp四边形不等式优化】
- dp四边形优化 Hdu 2829 Lawrence 题解
- HDU 2829 Lawrence【斜率优化dp】
- hdu 2829 Lawrence(二维DP+斜率优化)
- HDU 斜率优化dp 2829 Lawrence
- HDU 2829 Lawrence 斜率优化DP
- HDU 2829 Lawrence (斜率优化DP)
- HDU-2829-Lawrence-dp-斜率优化
- hdu 2829 Lawrence 斜率优化dp
- dp斜率优化 hdu 2829 Lawrence 题解
- 【斜率/四边形不等式DP】【hdu 2829】Lawrence
- android屏幕长度单位(dp与px)
- 【已解决】奇葩4: iOS定位,iPhone可以很快定位,但是iPad一直定位不了
- CentOS中安装gcc编译器
- 丢了身份证。。。
- 232 - Repeating Decimals
- hdu 2829 Lawrence (dp斜率优化||四边形优化)
- XML设置View的背景和代码中通过setBackground设置的背景尺寸不一
- android socket通信之传递有标识的值和解出值
- Cocos2d-X实现七夕情人节贺卡
- 强大的数组---Swift之Array
- HTTP协议详解
- 开发组长职责
- vs2008添加响应函数
- No known instance method for selector 'respondsToSelector:'