zoukankan      html  css  js  c++  java
  • POJ 1160 Post Office(抽象的二维DP)

    题意:

    有 n 个村庄,要求选定其中 p 个建立邮局,每个村庄使用离他最近的那个邮局,求一种方案使最终的距离总和最小;

    (黑书 157 邮局)

    思路:

    1. 题目中有 2 个“最”:最近的邮局、距离总和最小 -> 对于第一个最我们可以采取预处理的方式 cost[i, j] 即 i, j 之间建立一个邮局的最近距离;

    2. 最近的邮局这个很好解决:通过规律可以发现,如果邮局建在 i, j 的中间位置一定是最优的选择。下面解决距离总和最小;

    3. dp[i, j] 代表 前 i 个邮局建立在前 j 个村庄的最小距离总和。相当于是这 i 个邮局各有一片管辖区域,如何划分使总距离最小:

    4. 关于区间划分,这让人想到黑书上面任务调度类似的题目,推敲下有: dp[i, j] = min(dp[i, j], dp[i-1][k] + cost[k+1, j]);

     

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 310;
    const int INFS = 0x3fffffff;
    
    int dp[MAXN][MAXN], cost[MAXN][MAXN], x[MAXN];
    int vill, office;
    
    int calccost(int i, int j) {
        int ans = 0;
        while (i < j) {
            ans += x[j] - x[i];
            j--, i++;
        }
        return ans;
    }
    
    int workout() {
        for (int i = 0; i <= office; i++)
            for (int j = 0; j <= vill; j++)
                dp[i][j] = INFS;
        dp[0][0] = 0;
    
        for (int i = 1; i <= office; i++) {
            for (int j = i; j <= vill; j++) {
                for (int k = 0; k < j; k++)
                    dp[i][j] = min(dp[i][j], dp[i-1][k] + cost[k+1][j]);
            }
        }
        return dp[office][vill];
    }
    
    int main() {
        while (~scanf("%d%d", &vill, &office)) {
            x[0] = 0;
            for (int i = 1; i <= vill; i++)
                scanf("%d", &x[i]);
    
            for (int i = 1; i <= vill; i++)
                for (int j = i; j <= vill; j++)
                    cost[i][j] = calccost(i, j);
    
            printf("%d\n", workout());
        }
        return 0;
    }
  • 相关阅读:
    django-高级
    django-模板
    django-视图
    django笔记一
    redis、mysql、mongodb数据库
    Scrapy-redis分布式+Scrapy-redis实战
    python2 'ascii'编码问题
    【java8新特性】方法引用
    java浮点数运算无法精确的问题
    java中Array和ArrayList区别
  • 原文地址:https://www.cnblogs.com/kedebug/p/3006520.html
Copyright © 2011-2022 走看看