noi 162 post office dp

大致题意:

有v个村庄,每个村庄有各自的位置,且每个位置互不相同。现在要在村庄上设立P个邮局,使每个村庄到最近的邮局的距离之和最小。

分析:

定义状态d[i][j]表示前i个村庄,在这i个村庄中设立j个邮局的最小距离。s[i][j]表示村庄i至村庄j这几个村庄中设立一个邮局的最小距离。如果设立一个邮局,那么邮局设立在(a+b)/2这个位置是最优的。所以可以分解成以下子问题:

d[i][j]的最小值为d[k][j-1]的最小值加上s[k+1][i],s[k+1][i]为在k+1至i这几个村庄中设立一个邮局的最小距离。

d[i][j]=min(d[i][j], d[k][j-1]+s[k+1][i])

边界条件d[i][1]=s[1][i].

s数组可做如下优化:

s[1][4],把邮局设立在2和设立在3上距离是相同的。x2-x1+x3-x2+x4-x2与x3-x1+x3-x2+x4-x3相等。s[1][5]是把邮局设立在3上,s[1][5]=s[1][4]+x[5]-x[3]。由此,可得出递推式:s[i][j]=s[i][j-1]+x[j]-x[(i+j)/2].

#include <iostream>
#include <cstdio>
using namespace std;

const int INF=1e8;
int x[305];
int d[305][35];
int s[305][305];

int main()
{
    //freopen("in.txt","r",stdin);
    int n,p;
    while(~scanf("%d%d",&n,&p))
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&x[i]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<i && j<=p;j++)
                d[i][j]=INF;
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
                s[i][j]=s[i][j-1]+x[j]-x[(i+j)/2];
            d[i][1]=s[1][i];
        }
        for(int i=2;i<=n;i++)
            for(int j=2;j<=i && j<=p;j++)
                for(int k=j-1;k<i;k++)
                    d[i][j]=min(d[i][j],d[k][j-1]+s[k+1][i]);
        printf("%d\n",d[n][p]);
    }
    return 0;
}
时间: 2024-11-08 19:01:21

noi 162 post office dp的相关文章

162:Post Office

162:Post Office 总时间限制:  1000ms 内存限制:  65536kB 描述 There is a straight highway with villages alongside the highway. The highway is represented as an integer axis, and the position of each village is identified with a single integer coordinate. There ar

BZOJ 2436 Noi嘉年华(优化DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2436 题意:有一些活动,起始时间持续时间已知.有两个场地.每个活动最多只能在一个场地举行,且两个场地同一时间不能都举行活动.但是同一场地同一时间可以举行多个活动.要求的是两个场地中活动数目少的场地的活动数目的最大值S.再输出某个活动必须被安排时的S值. 思路:我直接粘贴原思路了. 区间离散化,设A={嘉年华1的活动}, B={嘉年华2的活动},C={未安排的活动}. 设num[i][j

【BZOJ 2436】 2436: [Noi2011]Noi嘉年华 (区间DP)

2436: [Noi2011]Noi嘉年华 Description NOI2011 在吉林大学开始啦!为了迎接来自全国各地最优秀的信息学选手,吉林大学决定举办两场盛大的 NOI 嘉年华活动,分在两个不同的地点举办.每个嘉年华可能包含很多个活动,而每个活动只能在一个嘉年华中举办. 现在嘉年华活动的组织者小安一共收到了 n个活动的举办申请,其中第 i 个活动的起始时间为 Si,活动的持续时间为Ti.这些活动都可以安排到任意一个嘉年华的会场,也可以不安排. 小安通过广泛的调查发现,如果某个时刻,两个嘉

hihocoder 1323 - 回文字符串 - [hiho一下162周][区间dp]

用dp[i][j]表示把[i,j]的字符串str改写成回文串需要的最小操作步数. 并且假设所有dp[ii][jj] (ii>i , jj<j)都为已知,即包括dp[i+1][j].dp[i][j-1].dp[i+1][j-1]这三者都已知,则: 1. 如果str[i]==str[j],那么dp[i][j]=dp[i+1][j-1]: 2. 否则dp[i][j]可以分为: ①"一个字符"+"一个回文串"型:那么我们可以在str[i,j]后面加上一个字符,或

poj 1185 炮兵阵地(状态压缩dp)

Description 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图.在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队):一支炮兵部队在地图上的攻击范围如图中黑色区域所示: 如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格.图上其它白色网格均攻击不

ACM 学习心得

ACM 学习心得 STL:完美的艺术品 STL 由四大部分组成:算法.容器.迭代器.仿函数. 算法(algorithm) 算法定义了一组与实现无关的操作,也是 ACM 学习的核心.C++ 算法库的内容全都是一些比较基本的算法,包括移动.转换.遍历.删除.过滤等等.C++ 算法库本身是基于抽象的,在迭代器的抽象下,使得这些算法可以在不同结构的容器中重用.一个比较坑的地方就是我高中的时候学完 C++ 之后报名了 NOIP.那一年刚刚允许用 STL(之前一直不准用),然后我对于标准库的依赖很严重,连快

html网页采集

UI_Less.pas: 1 unit UI_Less; 2 3 interface 4 5 uses 6 Windows, Classes, Messages, Forms, MsHtml, Urlmon, ActiveX; 7 8 const 9 WM_USER_STARTWALKING = WM_USER + 1; 10 DISPID_AMBIENT_DLCONTROL = (-5512); 11 READYSTATE_COMPLETE = $00000004; 12 13 DLCTL_D

20190809 B组总结

DP专题比赛…… T1: 赛中: 一道简单的DP题,直接根据题意设了一个四维数组然后推了推就做完了. 赛后: 这是正解(但是为什么这个要设为5000ms的限时???) 设个500ms都不为过…… 题目正解: DP T2: 赛中: 这个题好难,放弃治疗…… 什么,好像可以DFS 于是快乐的DFS过掉样例…… 赛后: 居然愉快的拿了37.5分 不错不错…… 可是大佬说这道题可以用矩阵乘法,但是得先推出DP转移式 题目正解: DP+矩阵乘法 T3: 赛中: 这不是一道水题吗? 可是瞬间尴尬,我又不会了

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿