zoukankan      html  css  js  c++  java
  • poj 1160 Post Office

    动态规划

    1.先考虑在1到n的村长里面放一个邮局的最优解,那么就是把邮局放在最中间的那个村庄处最优(若村庄数为偶数则最中间的村庄有两个哪个都可以)

    2.当放m个邮局的时候,其他每个邮局相当于有一个控制范围,范围内的村庄离该邮局最近,那么m个邮局会把n个村庄分为m块,我们就是dp每一块,令每一块的值最优,以及加上还没有处理的大块的最优解,则是我们要的答案

    dp[i][j]表示从1号到i号村庄放j个邮局的最优解

    方程:dp[i][j]=min{ dp[k-1][j-1]+s[k][i] }   s[k][i]表示在k号村庄到i号村庄放1个邮局的最优解,也就是放在最中间

    记忆化搜索

    /*
    dp[i][j]=min{ dp[k-1][j-1]+s[k][i] }
    */
    #include <cstdio>
    #include <cstring>
    #define INF 0x3f3f3f3f
    #define N 310
    #define M 35
    #define ABS(a,b) a-b>0?a-b:b-a
    #define min(a,b) a<b?a:b
    
    int dp[N][M],s[N][N],v[N],n,m;
    
    int sum(int a , int b)
    {
        int ans=0,mid=(a+b)>>1;
        for(int i=a; i<=b; i++)
            ans+=ABS(v[mid],v[i]);
        return ans;
    }
    
    int dfs(int i ,int j)
    {
        int mid,c,k;
        if(j==1)
        {
            dp[i][j]=0;
            mid=(1+i)>>1;
            for(c=1; c<=i; c++)
                dp[i][j]+=ABS(v[mid],v[c]);
            return dp[i][j];
        }
        if(dp[i][j]!=-1) return dp[i][j];
    
        dp[i][j]=INF;
        for(k=i; k>=j; k--) //当前分块的右边界
        {
            if(!s[k][i]) //还没有被计算过
                s[k][i]=sum(k,i);
            dp[k-1][j-1]=dfs(k-1,j-1);
            dp[i][j]=min(dp[i][j],dp[k-1][j-1]+s[k][i]);
        }
        return dp[i][j];
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(int i=1; i<=n; i++) scanf("%d",&v[i]);
            memset(dp,-1,sizeof(dp));
            memset(s,0,sizeof(s));
            dfs(n,m);
            printf("%d\n",dp[n][m]);
        }
        return 0;
    }

    递推

    /*
    递推版本,应该按照j从小往大递推
    dp[i][j]=min{ dp[k-1][j-1]+s[k][i] }
    */
    
    #include <cstdio>
    #include <cstring>
    #define INF 0x3f3f3f3f
    #define N 310
    #define M 35
    #define ABS(a,b) a-b>0?a-b:b-a
    #define min(a,b) a<b?a:b
    
    int dp[N][M],s[N][N],v[N],n,m;
    
    int sum(int a ,int b)
    {
        int ans=0,mid=(a+b)>>1;
        for(int i=a; i<=b; i++)
            ans+=ABS(v[mid],v[i]);
        return ans;
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(int i=1; i<=n; i++)
                scanf("%d",&v[i]);
            for(int i=1; i<=n; i++)
                for(int j=i; j<=n; j++)
                    s[i][j]=sum(i,j);
            for(int i=1; i<=n; i++)
                dp[i][1]=s[1][i];
    
            for(int j=2; j<=m; j++)
                for(int i=j; i<=n; i++)
                {
                    dp[i][j]=INF;
                    for(int k=i; k>=j; k--)
                        dp[i][j]=min(dp[i][j],dp[k-1][j-1]+s[k][i]);
                }
            printf("%d\n",dp[n][m]);
        }
        return 0;
    }
  • 相关阅读:
    pgspider sqlite mysql docker 镜像
    pgspider docker 镜像
    pgspider基于pg 的高性能数据可视化sql 集群引擎
    diesel rust orm 框架试用
    golang 条件编译
    Performance Profiling Zeebe
    bazel 学习一 简单java 项目运行
    一个好用node http keeplive agnet
    gox 简单灵活的golang 跨平台编译工具
    mailhog 作为smtp server mock工具
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2946256.html
Copyright © 2011-2022 走看看