zoukankan      html  css  js  c++  java
  • [题解] cogs 2240 架设电话线路

    http://cogs.pro:8080/cogs/problem/problem.php?pid=2240

    与洛谷P2885几乎一致,https://www.luogu.org/problemnew/show/P2885,双倍经验。

    定义dp[i][j]表示前i棵树的最大花费并且第i 棵树高度为j的。

    我们可以想到这某一棵树的高度与它前边的树有直接的关系,不难有一种想法。

    枚举第几棵树1->n

    枚举每棵树的高度$h[i]-> max { h[1],h[2]...h[n] } $

    枚举第i棵树前边那棵树也就是第i-1棵树的高度。

    现在我们想状态转移方程:

    当第i棵数的高度为j时,那么需要花费$(j-h[i])^2$,与前边好要有连起来那就需要找到abs(j-dp[i-1][h[i]->maxh])中的最小值。

    所以$dp[i][j]=min(dp[i][j],(j-h[i]^2+(j-dp[i-1][h[i]->maxh]) imes c))$.

    那么算法时间复杂度为$O(n imes h imes h)$.

    时间复杂度虽然比较高,奈何cogs数据比较水啊,勉强可以过。

    #include <cstdio>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    int min(int a,int b){ return a<b?a:b; }
    int n,a[100006],c,ans,f[100006][101];
    inline int read()
    {
        char c=getchar();
        int x=0;
        while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9')
          x=(x<<3)+(x<<1)+c-48,c=getchar();
        return x;
    }
    int main()
    {
        freopen("phonewire.in","r",stdin);
        freopen("phonewire.out","w",stdout);
        ans=0x7fffffff;
        scanf("%d%d",&n,&c);
        for(int i=1;i<=n;i++)a[i]=read();
        for(int i=1;i<=n;i++)
            for(int j=0;j<=100;j++)
                f[i][j]=1234567890;    
        for(int i=0;i<=100;i++)f[1][i]=(i-a[1])*(i-a[1]);
        for(int i=2;i<=n;i++)
        {
            for(int j=a[i];j<=100;j++)
            {
                for(int k=a[i-1];k<=100;k++)
                {
                    f[i][j]=min(f[i][j],f[i-1][k]+(j-a[i])*(j-a[i])+abs(k-j)*c);
                }
            }
        }
        for(int i=1;i<=100;i++)ans=min(ans,f[n][i]);
        printf("%d",ans);
        fclose(stdin);fclose(stdout);
    }

    然而洛谷上不吸氧的话就需要优化一下了(以下话语来自洛谷管理---redbag)

    不难发现,每次转移是个开口向上的二次函数(可以自己算算),然后我们枚举上一棵树的高度的过程中,

    如果随着高度的增加费用增加了,就可以不用继续转移了。

    #include<bits/stdc++.h>
    using namespace std;
    inline int read()
    {
        char s;
        int k=0,base=1;
        while((s=getchar())!='-'&&s!=EOF&&!(s>='0'&&s<='9'));
        if(s==EOF)exit(0);
        if(s=='-')base=-1,s=getchar();
        while(s>='0'&&s<='9')
        {
            k=k*10+(s-'0');
            s=getchar();
        }
        return k*base;
    }
    inline void write(int x)
    {
        if(x<0)
        {
            putchar('-');
            write(-x);
        }
        else
        {
            if(x/10)write(x/10);
            putchar(x%10+'0');
        }
    }
    int n,c,p,x,s,mh;
    int h[100100];
    int f[100100][100];
    int main()
    {
        n=read();
        c=read();
        for (register int i=1; i<=n; i++)
        {
            h[i]=read();
            if (h[i]>mh) mh=h[i];
        }
        memset(f,1,sizeof(f));
        for (register int i=h[1]; i<=100; i++) f[1][i]=(i-h[1])*(i-h[1]);
        for (register int i=2; i<=n; i++)
        {
            for (register int j=h[i]; j<=mh; j++) //hm:电线杆的最大高度
            {
                s=(j-h[i])*(j-h[i]);//先算出来快些?
                p=233333333;
                for (register int k=h[i-1]; k<=mh; k++)
                {
                    x=f[i-1][k]+s+c*abs(k-j);
                    //下面和这一句是等效的,似乎快点?f[i][j]=min(f[i][j],x);
                    if (x<f[i][j])
                    {
                        f[i][j]=x;
                    }
                    if (x>p) break;//比上一个更多就不用转移了
                    p=x;
                }
            }
        }
        int ans=f[n][h[n]];
        for (register int i=h[n]+1; i<=100; i++) ans=min(ans,f[n][i]); //找答案
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    spark 读取mongodb失败,报executor time out 和GC overhead limit exceeded 异常
    在zepplin 使用spark sql 查询mongodb的数据
    Unable to query from Mongodb from Zeppelin using spark
    spark 与zepplin 版本兼容
    kafka 新旧消费者的区别
    kafka 新生产者发送消息流程
    spark ui acl 不生效的问题分析
    python中if __name__ == '__main__': 的解析
    深入C++的new
    NSSplitView
  • 原文地址:https://www.cnblogs.com/rmy020718/p/9581584.html
Copyright © 2011-2022 走看看