HDU 3507 Print Article 斜率优化

Print Article


Time
Limit: 9000/3000 MS (Java/Others)    Memory
Limit: 131072/65536 K (Java/Others)
Total Submission(s):
4810    Accepted Submission(s):
1451

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 this
degree.
One day Zero want to print an article which has N words,
and each word i has a cost Ci to be printed. Also, Zero know that
print k words in one line will cost



M is a const number.
Now Zero want to know the minimum cost
in order to arrange the article perfectly.

Input

There are many test cases. For each test
case, There are two numbers N and M in the first line (0 ≤ n ≤ 500000, 0 ≤ M ≤ 1000). Then, there are N
numbers in the next 2 to N + 1 lines. Input are terminated by
EOF.

Output

A single number, meaning the mininum cost
to print the article.

Sample Input

5 5 5 9 5 7
5

Sample Output

230

第一次写斜率优化,代码很丑。

斜率优化模式为dp[i]=min(a[j]*b[i]+c[j])+d[i]

与本题f[i]=min(f[j]-2*sum[j]*sum[i]+sum[j]^2)+sum[i]^2+m相符。

另外,表示凸包写的还是很不熟练。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define MAXN 510000
#define INF 0x3f3f3f3f
//AC
int n,m;
int num[MAXN];
typedef long long qword;
qword f[MAXN];
qword sum[MAXN];
inline qword sqr(int x)
{
return x*x;
}
//f[i]=min(f[j]-2*sum[j]*sum[i]+sum[j]^2)+sum[i]^2+m
//f[i]=-2*sum[j]*sum[i] + f[j]+sum[j]^2 +sum[i]^2 + m
// -2*sum[i]*sum[j] + sum[i]^2-f[i]+m == -f[j]-sum[j]^2
struct Point
{
qword x,y;
void init(qword xx,qword yy)
{
x=xx;y=yy;
}
};
Point make_point (qword x,qword y)
{
Point ret;
ret.init(x,y);
return ret;
}
qword xmul(Point p1,Point p2,Point p3)
{
return (p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x);
}
double get_k(Point p1,Point p2)
{
if (p1.x==p2.x)throw "error";
return (double)(p2.y-p1.y)/(p2.x-p1.x);
}
struct Convex_Hall
{
Point pl[MAXN];
double kk[MAXN];
int topl;
void clear()
{
topl=-1;
}

Convex_Hall()
{
topl=-1;
}
void add_point(Point pp)
{
if (topl<1)
{
pl[++topl]=pp;
if (topl==1&&pl[topl].x==pl[topl-1].x)
{
if (pl[topl].y<pl[topl-1].y)
{
topl--;
return ;
}else
{
pl[topl--]=pp;
return ;
}

}
if (topl==1)
{
kk[topl-1]=get_k(pl[topl-1],pl[topl]);
}
return ;
}
while (topl>=1&&xmul(pl[topl-1],pl[topl],pp)>=0)
{
topl--;
}
pl[++topl]=pp;
kk[topl-1]=get_k(pl[topl-1],pp);
}
void pm()
{
int i;
for(i=0;i<=topl;i++)
{
printf("(%d,%d) ",pl[i].x,pl[i].y);
}
printf("\n");
}
double get_maxb(double k)
{
int l,r,mid;
if (topl==-1)throw "Error";
if (topl==0)return pl[0].y-pl[0].x*k;
if (k>kk[0])return pl[0].y-pl[0].x*k;
if (k<kk[topl-1])return pl[topl].y-pl[topl].x*k;
l=0,r=topl;
while (l<r)
{
mid=(l+r)>>1;
if (kk[mid-1]>=k&&kk[mid]<=k)
{
return pl[mid].y-pl[mid].x*k;
}
if (kk[mid-1]<k)
{
r=mid;
}else
{
l=mid;
}
}
}
}H;

int main()
{
//freopen("input.txt","r",stdin);
int i;
while (~scanf("%d%d",&n,&m))
{
H.clear();
for (i=1;i<=n;i++)
{
scanf("%d",&num[i]);
sum[i]=sum[i-1]+num[i];
}
memset(f,INF,sizeof(f));
/* f[0]=0;
for (i=1;i<=n;i++)
{
for (j=0;j<i;j++)
{
if (f[j]>=INF)continue;
f[i]=min(f[i],f[j]+sqr(sum[i]-sum[j])+m);
}
}
for (i=1;i<=n;i++)cout<<f[i]<<" ";cout<<endl;
*/ f[0]=0;
H.add_point(make_point(sum[0],-sum[0]*sum[0]-f[0]));
double k,b;
for (i=1;i<=n;i++)
{
k=-2*sum[i];
b=H.get_maxb(k);
f[i]=sum[i]*sum[i]+m-ceil(b);
H.add_point(make_point(sum[i],-sum[i]*sum[i]-f[i]));
// cout<<f[i]<<" ";
}
cout<<f[n]<<endl;;
}
return 0;
}

HDU 3507 Print Article 斜率优化,布布扣,bubuko.com

时间: 2024-10-24 05:29:17

HDU 3507 Print Article 斜率优化的相关文章

hdu 3507 Print Article —— 斜率优化DP

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3507 设 f[i],则 f[i] = f[j] + (s[i]-s[j])*(s[i]-s[j]) + m 即 f[j] + s[j]*s[j] = 2*s[i]*s[j] + f[i] - s[i]*s[i] - m 于是维护下凸包即可: 写成 double 的 slp 总是不对,把分母乘到对面就对了... 代码如下: #include<iostream> #include<cstdio>

HDU 3507 Print Article (斜率DP)

题意:要输出N个数字a[N],输出的时候可以连续连续的输出,每连续输出一串,它的费用是 "这串数字和的平方加上一个常数M". 析:这个题很容易想到DP方程dp[i] = min{dp[j] + M + (sum[i]-sum[j])^2},但是很明显是O(n^2),TLE是必然的,所以要进行优化. 假设 i > j > k ,并且 j 要比 k 好,那么就是 dp[j] + M + (sum[i]-sum[j])^2 < dp[k] + M + (sum[i]-sum

HDU 3507 Print Article (斜率优化)

HDU 3507 Print Article (斜率优化) ACM 题目地址: HDU 3507 Print Article 题意: 给定一个长度为n的序列,和一个常数m,我们可以将序列分成随意段,每段的权值为sum(arr[i]) + C(x<=i<=y),求一种划分方法使得整个序列的权值最小 分析: from:亟隐's blog f[i]=min(f[k]+(sum(i)-sum(k))^2 )+m = f[k]+sum^2(i)+sum^2(k)-2*sum(i)*sum(k)+m. 也

HDU 3507 单调队列 斜率优化

斜率优化的模板题 给出n个数以及M,你可以将这些数划分成几个区间,每个区间的值是里面数的和的平方+M,问所有区间值总和最小是多少. 如果不考虑平方,那么我们显然可以使用队列维护单调性,优化DP的线性方法来做,但是该题要求的是区间和的平方,于是要转换单调的计算方法为斜率,也就是凸线. 其他就是最基本的单调DP /** @Date : 2017-09-04 15:39:05 * @FileName: HDU 3507 单调队列 斜率优化 DP.cpp * @Platform: Windows * @

斜率优化dp简讲 &amp;&amp; HDU 3507 Print Article

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

DP(斜率优化):HDU 3507 Print Article

Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 8199    Accepted Submission(s): 2549 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique

HDU 3507 Print Article(DP+斜率优化)

 Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 7960    Accepted Submission(s): 2465 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antiq

HDU 3507 Print Article(斜率优化)

Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 15536    Accepted Submission(s): 4813 Problem Description Zero has an old printer that doesn't work well sometimes. As it is antiqu

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