区间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\n",dp[n][pn]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/DF-yimeng/p/9354117.html

时间: 2024-11-10 15:18:31

区间DP POJ1160村庄邮局问题的相关文章

POJ 1160 (区间DP+四边形优化)

这个转移方程不好想,尤其是一段值的解是中间,不明觉厉.dp[i][j] 用i个邮局,覆盖前j个村庄的最小值. 还有就是区间dp的平行四边形优化,这个题的转移方程并不是"区间DP",所以枚举状态要逆着(很花时间),且用一个邮局覆盖都是从0断开了相当于没有断开. 类比于石子归并,矩阵链乘等标准区间DP,其所需状态之前就已经获得,不用倒推 #include <cstdio> #include <cstring> #include <iostream> us

区间dp——POJ - 1160

题目含义 v个村庄要建p个邮局 现给出每个村庄的位置,并且邮局只能建在村庄的位置 问每个村庄到离它最近的邮局距离之和最小为多少 题目分析 区间dp[i][j]表示在前i个村庄建j个邮局的最小距离 dp[i][j]=min(dp[i][j],dp[k][j-1]+dis[k+1][j]) 这个状态方程表示,将[在前i个村庄建j个邮局的距离]划分成[在前k个村庄建j-1个邮局的距离]加上[在第k+1个村庄到第j个村庄之间建一个邮局的距离] 题目代码 #include<iostream> #incl

P1220 关路灯 区间DP

题目描述 某一村庄在一条路线上安装了n盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少).老张就住在这条路中间某一路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关掉这些路灯. 为了给村里节省电费,老张记录下了每盏路灯的位置和功率,他每次关灯时也都是尽快地去关,但是老张不知道怎样去关灯才能够最节省电.他每天都是在天亮时首先关掉自己所处位置的路灯,然后可以向左也可以向右去关灯.开始他以为先算一下左边路灯的总功率再算一下右边路灯的总功率,然后选择先关掉功率大的一边,再回过头来关掉另一边

区间dp②

区间dp的第②篇,稍微有点难度 关路灯 题目描述 某一村庄在一条路线上安装了n盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少).老张就住在这条路中间某一路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关掉这些路灯. 为了给村里节省电费,老张记录下了每盏路灯的位置和功率,他每次关灯时也都是尽快地去关,但是老张不知道怎样去关灯才能够最节省电.他每天都是在天亮时首先关掉自己所处位置的路灯,然后可以向左也可以向右去关灯.开始他以为先算一下左边路灯的总功率再算一下右边路灯的总功率,然后选择

P4677 山区建小学|区间dp

P4677 山区建小学 题目描述 政府在某山区修建了一条道路,恰好穿越总共nn个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往.已知任意两个相邻的村庄之间的距离为di 为了提高山区的文化素质,政府又决定从n个村中选择m个村建小学. 请根据给定的n.m以及所有相邻村庄的距离,选择在哪些村庄建小学,才使得所有村到最近小学的距离总和最小,计算最小值. 题解:https://www.luogu.org/blog/hsfzLZH1/solution-p4677 区间dp主要是下面这几段

uva 10003 Cutting Sticks 简单区间dp

// uva 10003 Cutting Sticks 区间dp // 经典的区间dp // dp(i,j)表示切割小木棍i-j所需要的最小花费 // 则状态转移为dp(i,j) = min{dp(i,k) + dp(k,j) + a[j]-a[i]) // 其中k>i && k<j // a[j] - a[i] 为第一刀切割的代价 // a[0] = 0,a[n+1] = L; // dp数组初始化的时候dp[i][i+1]的值为 0,这表示 // 每一段都已经是切割了的,不

黑书例题 Fight Club 区间DP

题目可以在bnuoj.soj等OJ上找到. 题意: 不超过40个人站成一圈,只能和两边的人对战.给出任意两人对战的输赢,对于每一个人,输出是否可能是最后的胜者. 分析: 首先序列扩展成2倍,破环成链. dp[i][j]表示i和j能够相遇对打,那么dp[i][i+n]为真代表可以成为最后胜者. 枚举中间的k,若i和j都能和k相遇,且i和j至少一人能打赢k,那么i和j可以相遇. 复杂度o(n^3) 1 #include<cstdio> 2 #include<cstring> 3 usi

算法复习——区间dp

感觉对区间dp也不好说些什么直接照搬讲义了2333 例题: 1.引水入城(洛谷1514) 这道题先开始看不出来到底和区间dp有什么卵关系···· 首先肯定是bfs暴力判一判可以覆盖到哪些城市····无解直接输出···有解得话就要想想了···· 这道题关键是要发现··如果一个蓄水池所在城市可以覆盖到一些沙漠城市···那么这些沙漠城市肯定是一段····不然假设有一个城市是断开的而两边都被同一个蓄水池流出的水覆盖,这个城市四周的城市都肯定比它矮···(不理解举个反例吧···反正我举不出来)···然后就

合并石子 区间dp水题

合并石子 链接: nyoj 737 描述: 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆.求出总的代价最小值. tags:最基本的区间dp,这题范围小,如果n大一些,还是要加个平行四边行优化. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring&g