码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 1705: [Usaco2007 Nov]Telephone Wire 架设电话线【dp】

时间:2018-06-22 23:52:12      阅读:216      评论:0      收藏:0      [点我收藏+]

标签:5*   min   ==   查错   ace   i++   时间   直接   play   

i的初始化写成2了于是成功查错2h……怕不是个傻子
设f[i][j]为第i根高为j,转移是
\[ f[i][j]=min(f[i-1][k]+abs(k-j)*c+(j-h[i])^2)(j>=h[i],k>=h[i-1]) \]
时间复杂度是1e5*1e2*1e2,空间复杂度是1e5*1e2,显然都过不了
abs很碍眼,所以考虑分两种情况,化简之后就是
\[ f[i][j]=min(f[i-1][k]+k*c)-j*c+(j-h[i])^2(j>=h[i],k>=h[i-1],k>=j) \]
\[ f[i][j]=min(f[i-1][k]-k*c)+j*c+(j-h[i])^2(j>=h[i],k>=h[i-1],k<j) \]
然后另开数组ad[i][j]表示i根从j到100最大的f[i][j]+jc,mi[i][j]表示i根从a[i]到j最大的f[i][j]-jc,这个可以在求完f[i][]之后直接扫一遍求出,这样时间复杂度就降为了1e5*1e2
然后发现f,ad,mi的i维都没用,所以直接推掉,空间复杂度就变成了1e2(还有1e5的h数组)
就没了

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100005,inf=1e9;
int n,c,a[N],f[105],ad[105],mi[105],ans=inf;
int read()
{
    int r=0,f=1;
    char p=getchar();
    while(p>‘9‘||p<‘0‘)
    {
        if(p==‘-‘)
            f=-1;
        p=getchar();
    }
    while(p>=‘0‘&&p<=‘9‘)
    {
        r=r*10+p-48;
        p=getchar();
    }
    return r*f;
}
int main()
{
    n=read(),c=read();
    for(int i=1;i<=n;i++)
        a[i]=read();
    for(int i=a[1];i<=100;i++)
        f[i]=(i-a[1])*(i-a[1]);
    for(int i=1;i<=n;i++)
    {
        if(i!=1)
            for(int j=a[i];j<=100;j++)
                f[j]=min(mi[j]+j*c,ad[max(a[i-1],j+1)]-j*c)+(j-a[i])*(j-a[i]);
        for(int j=0;j<=101;j++)
            ad[j]=mi[j]=inf;
        for(int j=a[i];j<=100;j++)
            mi[j]=min(mi[j-1],f[j]-j*c);
        for(int j=100;j>=a[i];j--)
            ad[j]=min(ad[j+1],f[j]+j*c);
    }
    for(int i=a[n];i<=100;i++)
        ans=min(ans,f[i]);
    printf("%d\n",ans);
    return 0;
}

bzoj 1705: [Usaco2007 Nov]Telephone Wire 架设电话线【dp】

标签:5*   min   ==   查错   ace   i++   时间   直接   play   

原文地址:https://www.cnblogs.com/lokiii/p/9215657.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!