• 区间DP POJ1160村庄邮局问题


    POJ1160

    题目大意:一系列村庄在一维坐标系上有序的排列,建设p个邮局,问各个村庄到邮局的最短距离和。

    线性区间DP问题

    dp数组的值为最短/最优距离

    村庄和邮局为限制

    dp[i][j]表示前i个村庄有j个邮局的最优解

    分析最小子问题可得前i个村庄有1个邮局的最优解——中间的村庄

    所以分解区间dp[i][j] = min(dp[i][j],dp[k][j-1] + sum[k+1][i])

    sum[i][j]数组表示从i到j村庄放一个邮局的最优解

    j,i,k的遍历,最终得到最优解

    外层遍历的是邮局的个数,这样才能遍历村庄的个数(我们所未知的情况是村庄的个数大于邮局的个数)

    对了sum【i】【j】和sum[i][j-1]存在某种关系呦,一推就出来了~~

    #include <iostream>
    #include <cstdio>
    #include <string.h>
    #define inf (1e8 + 9e7)
    using namespace std;
    const int maxn = 1e3 + 1e2;
    int dp[maxn][maxn];
    int sum[maxn][maxn];
    int pos[maxn];
    void init()
    {
        memset(sum,0,sizeof(sum));
    }
    int main()
    {
        int n,pn;
        while(~scanf("%d%d",&n,&pn))
        {
            init();
            for(int i = 1;i <= n;i++)
                scanf("%d",&pos[i]);
    
            for(int i = 1;i <= n;i++)
            {
                for(int j = i+1;j <= n;j++)
                {
                    sum[i][j] = sum[i][j-1] + pos[j] - pos[(i + j)/2];
                }
                dp[i][i] = 0;
            }
    
            for(int i = 1;i <= n;i++)
            {
                dp[i][1] = sum[1][i];
            }
    
            for(int j = 2;j <= pn;j++)//建造一个的情况已经铺垫好了
                for(int i = j+1;i <= n;i++)//村庄首先必须保证得比
                {
                    //接下来我要做的是遍历k来找到到底几个村庄放j-1个最优
                    dp[i][j] = inf;
                    for(int k = j - 1;k < i;k++)
                    {
                        dp[i][j] = min(dp[i][j],dp[k][j-1] + sum[k+1][i]);
                    }
                }
            printf("%d
    ",dp[n][pn]);
        }
        return 0;
    }
    
  • 相关阅读:
    sql优化
    什么是泛型
    Http Status 400
    Hadoop搭建伪分布式 & 上传和下载文件
    Centos64 安装指南
    个人感悟
    zabbix4.0部署
    MySQL引擎
    mysql正则表达式
    k8s自动补全命令
  • 原文地址:https://www.cnblogs.com/DF-yimeng/p/9354117.html
Copyright © 2020-2023  润新知