信息学奥赛一本通 1197:山区建小学 | OpenJudge NOI 2.6 7624:山区建小学 | 洛谷 P4677 山区建小学

本文主要是介绍信息学奥赛一本通 1197:山区建小学 | OpenJudge NOI 2.6 7624:山区建小学 | 洛谷 P4677 山区建小学,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【题目链接】

ybt 1197:山区建小学
OpenJudge NOI 2.6 7624:山区建小学
洛谷 P4677 山区建小学

【题目考点】

1. 动态规划:区间动规
2. 前缀和

【解题思路】

1. 求相邻多村中建一所小学,各村上学的最短距离

现在准备在第i村到第j村中建立一所小学,从第i村到第j村的学生都只能上这一所小学。考虑将小学建在哪个村里,可以使得第i到第j各村的学生上学距离加和最短?
在这里插入图片描述

上图用一条线段上的点表示各个村,包括第i,i+1,i+2,…,j-1,j村。
相邻两村之间的距离是已知的,已知第 x x x到第 x + 1 x+1 x+1村的距离为 d x d_x dx,设在第p村建学校。
证明: p = i + j 2 p=\frac{i+j}{2} p=2i+j时,在第 p p p村建学校,各村上学的距离总和最小。

引理1:将学校从第k-1村移到第k村,上学总距离减少: s d = ( i + j + 1 − 2 k ) d k − 1 sd=(i+j+1-2k)d_{k-1} sd=(i+j+12k)dk1
证明:考虑特殊情况:

  • 如果 p = i p=i p=i,那么总距离加和为: ∑ y = i j − 1 ( ∑ x = i y d x ) \sum_{y=i}^{j-1}(\sum_{x=i}^{y}d_x) y=ij1(x=iydx)
  • 如果 p = i + 1 p=i+1 p=i+1,相比于 p = i p=i p=i,从 i i i村距离0, i + 1 i+1 i+1村距离 d i d_i di,变为 i + 1 i+1 i+1村距离0, i i i村距离增加 d i d_i di,这部分的距离没变。从第 i + 2 i+2 i+2 j j j村每个村的距离都减少了 d i d_i di,总共减少距离 ( j − i − 1 ) d i (j-i-1)d_i (ji1)di
  • 如果 p = i + 2 p=i+2 p=i+2,相比于 p = i + 1 p=i+1 p=i+1,原来 i + 2 i+2 i+2村的距离变为 i + 1 i+1 i+1村的距离, i i i村的距离增加 d i + 1 d_{i+1} di+1,从第 i + 3 i+3 i+3 j j j每个村距离减少 d i + 1 d_{i+1} di+1,全部加起来总共减少 ( j − i − 3 ) d i + 1 (j-i-3)d_{i+1} (ji3)di+1

考虑一般情况:

  • 如果 p = k p=k p=k,相比于 p = k − 1 p=k-1 p=k1,原来 k k k村的距离变为 k − 1 k-1 k1村的距离,
    从第 i i i k − 2 k-2 k2村每村上学距离增加了 d k − 1 d_{k-1} dk1,共增加距离 ( k − i − 1 ) d k − 1 (k-i-1)d_{k-1} (ki1)dk1
    从第 k + 1 k+1 k+1 j j j村每村上学距离减少了 d k − 1 d_{k-1} dk1,共减少距离 ( j − k ) d k − 1 (j-k)d_{k-1} (jk)dk1
    总减少距离 s d sd sd ( j − k ) d k − 1 − ( k − i − 1 ) d k − 1 (j-k)d_{k-1}-(k-i-1)d_{k-1} (jk)dk1(ki1)dk1
    即将学校从第k-1村移到第k村,总距离减少: s d = ( i + j + 1 − 2 k ) d k − 1 sd=(i+j+1-2k)d_{k-1} sd=(i+j+12k)dk1

证明: p = i + j 2 p=\frac{i+j}{2} p=2i+j时,在第 p p p村建学校,各村上学的距离总和最小。
考虑从 i i i j j j的数字个数的奇偶性

  • 如果从 i i i j j j一共有偶数个数字,那么 i , j i,j i,j奇偶性不同, i + j + 1 i+j+1 i+j+1为偶数,能整除2。
    • 如果 k < i + j + 1 2 k <\frac{i+j+1}{2} k<2i+j+1,那么 s d = ( i + j + 1 − 2 k ) d k − 1 > 0 sd = (i+j+1-2k)d_{k-1} > 0 sd=(i+j+12k)dk1>0,将学校从 k − 1 k-1 k1村移动到 k k k村后总距离减少。
    • 如果 k = i + j + 1 2 k=\frac{i+j+1}{2} k=2i+j+1,从 k − 1 k-1 k1村移动到 k k k村距离不变。
    • 如果 k > i + j + 1 2 k>\frac{i+j+1}{2} k>2i+j+1,那么 s d = ( i + j + 1 − 2 k ) d k − 1 < 0 sd = (i+j+1-2k)d_{k-1} < 0 sd=(i+j+12k)dk1<0,减少的距离为负值,即为增加距离。将学校从 k − 1 k-1 k1村移动到 k k k村后的总距离增加。
    • 因此在第 i + j − 1 2 \frac{i+j-1}{2} 2i+j1 i + j + 1 2 \frac{i+j+1}{2} 2i+j+1村,建学校可以让距离总和最小。考虑整除运算,此时 i + j 2 = i + j − 1 2 \frac{i+j}{2}=\frac{i+j-1}{2} 2i+j=2i+j1,所以也可以说在第 i + j 2 \frac{i+j}{2} 2i+j村建学校可以使得距离总和最小。
  • 如果从 i i i j j j一共有奇数个数字,那么 i , j i,j i,j奇偶性相同, i + j i+j i+j为偶数。
    • k k k i + j 2 \frac{i+j}{2} 2i+j时,减少距离 s d = d k − 1 > 0 sd=d_{k-1}>0 sd=dk1>0,即将学校从第 i + j 2 − 1 \frac{i+j}{2}-1 2i+j1村移到 i + j 2 \frac{i+j}{2} 2i+j村,总距离减少。
    • k k k i + j 2 + 1 \frac{i+j}{2}+1 2i+j+1时,减少距离 s d = − d k − 1 < 0 sd=-d_{k-1}<0 sd=dk1<0,即将学校从第 i + j 2 \frac{i+j}{2} 2i+j村移到 i + j 2 + 1 \frac{i+j}{2}+1 2i+j+1村,总距离增加。
    • 因此在第 i + j 2 \frac{i+j}{2} 2i+j村建学校,距离总和最小。

c i , j c_{i,j} ci,j表示从第i村到第j村建只一所小学,且从第i村到第j村都上这一所小学,上学的距离加和的最小值。根据上述结论,应该在第 i + 1 2 \frac{i+1}{2} 2i+1村建小学。
s i s_i si表示第i村到第1村的距离,那么 s i = ∑ x = 1 i − 1 d x s_i=\sum_{x=1}^{i-1}d_x si=x=1i1dx
那么第i村到第j村的距离 ∑ x = i j − 1 d x \sum_{x=i}^{j-1}d_x x=ij1dx s j − s i s_j-s_i sjsi,类似前缀和。
该问题可以作为一个小的动态规划问题来解, c i , j c_{i,j} ci,j为状态

  • 初始状态: c i , i c_{i,i} ci,i,从第i村到第i村建1所小学,那么就在第i村建,第i村的学生上学走路距离为0,所以对于任意i,有 c i , i = 0 c_{i,i}=0 ci,i=0
  • 状态转移:
    • 已知从第i村到第j-1村,在第 i + j − 1 2 \frac{i+j-1}{2} 2i+j1村建小学,距离总和为 c i , j − 1 c_{i,j-1} ci,j1
    • 现在要考虑第i村到第j村,到第 i + j − 1 2 \frac{i+j-1}{2} 2i+j1村的小学上学,第j村到第 i + j − 1 2 \frac{i+j-1}{2} 2i+j1村的距离为 s j − s ( i + j − 1 ) / 2 s_j-s_{(i+j-1)/2} sjs(i+j1)/2,距离总和为 c i , j − 1 + s j − s ( i + j − 1 ) / 2 c_{i,j-1}+s_j-s_{(i+j-1)/2} ci,j1+sjs(i+j1)/2
    • 现在要将在第 i + j − 1 2 \frac{i+j-1}{2} 2i+j1村的小学移到第 i + j 2 \frac{i+j}{2} 2i+j村。
      • 如果i+j是奇数,那么 i + j − 1 2 = i + j 2 \frac{i+j-1}{2} = \frac{i+j}{2} 2i+j1=2i+j,小学没有移动。距离总和可以写为: c i , j − 1 + s j − s ( i + j ) / 2 c_{i,j-1}+s_j-s_{(i+j)/2} ci,j1+sjs(i+j)/2
      • 如果i+j是偶数,那么 i + j − 1 2 = i + j 2 − 1 \frac{i+j-1}{2} = \frac{i+j}{2}-1 2i+j1=2i+j1
        根据引理1:将学校从第 i + j 2 − 1 \frac{i+j}{2}-1 2i+j1村移到第 i + j 2 \frac{i+j}{2} 2i+j村,上学总距离减少: s d = ( i + j + 1 − 2 ∗ i + j 2 ) d ( i + j ) / 2 − 1 = d ( i + j ) / 2 − 1 sd=(i+j+1-2*\frac{i+j}{2})d_{(i+j)/2-1}=d_{(i+j)/2-1} sd=(i+j+122i+j)d(i+j)/21=d(i+j)/21
        距离总和为: c i , j − 1 + s j − s ( i + j − 1 ) / 2 − d ( i + j ) / 2 − 1 = c i , j − 1 + s j − ( s ( i + j ) / 2 − 1 + d ( i + j ) / 2 − 1 ) = c i , j − 1 + s j − s ( i + j ) / 2 c_{i,j-1}+s_j-s_{(i+j-1)/2}-d_{(i+j)/2-1}=c_{i,j-1}+s_j-(s_{(i+j)/2-1}+d_{(i+j)/2-1})=c_{i,j-1}+s_j-s_{(i+j)/2} ci,j1+sjs(i+j1)/2d(i+j)/21=ci,j1+sj(s(i+j)/21+d(i+j)/21)=ci,j1+sjs(i+j)/2

因此得到状态转移方程为: c i , j = c i , j − 1 + s j − s ( i + j ) / 2 c_{i,j}=c_{i,j-1}+s_j-s_{(i+j)/2} ci,j=ci,j1+sjs(i+j)/2
c[i][j] = c[i][j-1] + s[j] - s[(i+j)/2]

另一种写法,也可以直接通过前缀和求c数组。
求从第i村到第j村每个村到第 i + 1 2 \frac{i+1}{2} 2i+1村的距离加和
c i , j = ∑ x = i ( i + j ) / 2 − 1 ( s ( i + j ) / 2 − s x ) + ∑ x = ( i + j ) / 2 + 1 j ( s x − s ( i + j ) / 2 ) c_{i,j} = \sum_{x=i}^{(i+j)/2-1}(s_{(i+j)/2}-s_x)+\sum_{x=(i+j)/2+1}^{j}(s_x-s_{(i+j)/2}) ci,j=x=i(i+j)/21(s(i+j)/2sx)+x=(i+j)/2+1j(sxs(i+j)/2)
本质上和第一种写法是一样的。由该式也可以推出上述递推公式。

2. 求前i个村建j个学校的最小距离和
  • 确定状态定义:
    集合:建学校的方案
    限制:哪些村,建学校个数
    属性:各村到最近学校距离和
    条件:最小
    统计量:各村到最近学校距离和
    状态定义dp[i][j]: 前i个村建j所小学,且前i个村就只去这j所小学的情况下,各村到最近学校的距离和。
    初始状态:前i个村建1所小学,距离和为 c 1 , i c_{1,i} c1,i,所以dp[i][1] = c[1][i]
  • 确定状态转移方程:
    前i个村要建j所小学,考虑最后建的一所小学要让哪些使用村。
    前i-1个村建j-1所小学,第j所小学给第i村使用。dp[i][j] = dp[i-1][j-1]+c[i][i]
    前i-2个村建j-1所小学,第j所小学给第i-1到第i村使用。dp[i][j] = dp[i-2][j-1]+c[i-1][i]前i-3个村建j-1所小学,第j所小学给第i-2到第i村使用。dp[i][j] = dp[i-3][j-1]+c[i-2][i]

    前k个村建j-1所小学,第j所小学给第k+1到第i村使用,在第k+1到第i村建一所使得这些村的学生上学距离加和最短的小学,需要在第 k + 1 + i 2 \frac{k+1+i}{2} 2k+1+i村建校,距离加和为c[k+1][i]。所以总加和为:dp[i][j] = dp[k][j-1]+c[k+1][i]
    k最小为j-1,即前j-1个村建j-1所小学,每个村一所,k最大为i-1,这样可以在第i村建第j所学校。
    状态转移方程为:
    k从j-1循环到i-1,求dp[i][j] = dp[k][j-1]+c[k+1][i]的最小值。

前i个村建j所小学,有m个村,最多n个小学。
i从1循环到m,j从1循环到n。如果 j > = i j>=i j>=i,可以保证每个村一所学校,总距离为0。所以j只需要循环到 i − 1 i-1 i1即可。所以j的循环条件为 j < = n j<=n j<=n j < i j<i j<i

【题解代码】

解法1:区间动规
  • 通过递推求c数组
#include<bits/stdc++.h>
using namespace std;
#define N 505
#define INF 0x3f3f3f3f
int d[N], s[N];//d[i]:第i村到第i+1村的距离 s[i]:第i村到第1村的距离 
int c[N][N];//c[i][j]:第i村到第j村建1所小学,且都上这所小学的最小距离 
int dp[N][N];//dp[i][j]:前i个村建j所小学,且都上这些小学的最小距离 
int main()
{int n, m;cin >> m >> n;for(int i = 1; i <= m - 1; ++i){cin >> d[i];s[i+1] = s[i] + d[i];}for(int i = 1; i <= m; ++i)for(int j = i; j <= m; ++j)c[i][j] = c[i][j-1] + s[j] - s[(i+j)/2];for(int i = 1; i <= m; ++i)dp[i][1] = c[1][i];for(int i = 1; i <= m; ++i)for(int j = 2; j <= n && j < i; ++j){dp[i][j] = INF;for(int k = j - 1; k <= i - 1; ++k)dp[i][j] = min(dp[i][j], dp[k][j-1] + c[k+1][i]);}cout << dp[m][n]; return 0;
}
  • 通过前缀和直接求c数组
#include<bits/stdc++.h>
using namespace std;
#define N 505
#define INF 0x3f3f3f3f
int d[N], s[N];//d[i]:第i村到第i+1村的距离 s[i]:第i村到第1村的距离 
int c[N][N];//c[i][j]:第i村到第j村建1所小学,且都上这所小学的最小距离 
int dp[N][N];//dp[i][j]:前i个村建j所小学,且都上这些小学的最小距离 
int main()
{int n, m;cin >> m >> n;for(int i = 1; i <= m - 1; ++i){cin >> d[i];s[i+1] = s[i] + d[i];}for(int i = 1; i <= m; ++i)for(int j = i; j <= m; ++j){int mid = (i+j)/2;for(int k = i; k <= mid-1; ++k)c[i][j] += s[mid] - s[k];for(int k = mid+1; k <= j; ++k)c[i][j] += s[k] - s[mid];}for(int i = 1; i <= m; ++i)dp[i][1] = c[1][i];for(int i = 1; i <= m; ++i)for(int j = 2; j <= n && j < i; ++j){dp[i][j] = INF;for(int k = j - 1; k <= i - 1; ++k)dp[i][j] = min(dp[i][j], dp[k][j-1] + c[k+1][i]);}cout << dp[m][n]; return 0;
}

这篇关于信息学奥赛一本通 1197:山区建小学 | OpenJudge NOI 2.6 7624:山区建小学 | 洛谷 P4677 山区建小学的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/369565

相关文章

uva 11044 Searching for Nessy(小学数学)

题意是给出一个n*m的格子,求出里面有多少个不重合的九宫格。 (rows / 3) * (columns / 3) K.o 代码: #include <stdio.h>int main(){int ncase;scanf("%d", &ncase);while (ncase--){int rows, columns;scanf("%d%d", &rows, &col

生信代码入门:从零开始掌握生物信息学编程技能

少走弯路,高效分析;了解生信云,访问 【生信圆桌x生信专用云服务器】 : www.tebteb.cc 介绍 生物信息学是一个高度跨学科的领域,结合了生物学、计算机科学和统计学。随着高通量测序技术的发展,海量的生物数据需要通过编程来进行处理和分析。因此,掌握生信编程技能,成为每一个生物信息学研究者的必备能力。 生信代码入门,旨在帮助初学者从零开始学习生物信息学中的编程基础。通过学习常用

生信圆桌x生信分析平台:助力生物信息学研究的综合工具

介绍 少走弯路,高效分析;了解生信云,访问 【生信圆桌x生信专用云服务器】 : www.tebteb.cc 生物信息学的迅速发展催生了众多生信分析平台,这些平台通过集成各种生物信息学工具和算法,极大地简化了数据处理和分析流程,使研究人员能够更高效地从海量生物数据中提取有价值的信息。这些平台通常具备友好的用户界面和强大的计算能力,支持不同类型的生物数据分析,如基因组、转录组、蛋白质组等。

JeecgBoot 升级springboot版本到2.6.0

1. 环境描述 Jeecgboot 3.0,他所依赖的springboot版本为2.3.5Release,将springboot版本升级为2.6.0。过程全纪录,从2开始描述。 2. 修改springboot版本号 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-pare

【生物信息学算法】图算法1:概念和算法

文章目录 1. 图的定义、分类、表达方式图的定义图的分类表达方式Python实现 2.相邻节点和度概念定义python实现 3.路径、距离和搜索路径和距离搜索环 4.图论中的欧拉定理 1. 图的定义、分类、表达方式 图的定义 图G可以由两个集合来定义,即G=(V,E)。其中,V是对象的集合,称为图的顶点或节点; E是V中(u,v)顶点对的集合,称为边或弧,表示u和v之间的关系

高精度计算(代码加解析,洛谷p1601,p1303)除法待更新

目录 高精度加法 高精度减法 高精度乘法 高精度加法 我们知道在c++语言中任何数据类型都有一定的表示范围。当两个被加数很大时,正常加法不能得到精确解。在小学,我们做加法都采用竖式方法。那么我们也只需要按照加法进位的方式就能得到最终解。 8 5 6+ 2 5 5-------1 1 1 1 加法进位: c[i] = a[i] + b[i];if(c[i] >=

洛谷 凸多边形划分

T282062 凸多边形的划分 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 先整一个半成品,高精度过两天复习一下补上 #include <iostream>#include <algorithm>#include <set>#include <cstring>#include <string>#include <vector>#include <map>

能量项链,洛谷

解释:  环形dp问题还是考虑将环拉直,可以参考我上一篇文章:环形石子合并 [2 3 5 10 2] 3 5 10 将环拉直,[]内是一个有效的区间,可以模拟吸收珠子的过程,         如[2 3 5] <=>(2,3)(3,5)    2是头,3是中间,5是尾 len >= 3:因为最后[2 10 2]是最小的可以合并的有效区间 len <= n + 1因为[2 3

【简历】25届南京某一本JAVA简历:简历通过率还好,但是拿不到OFFER

注:为保证用户信息安全,姓名和学校等信息已经进行同层次变更,内容部分细节也进行了部分隐藏 简历说明 今天看一份25届南京某一本大学的Java简历。 这个简历呢,学校是一本。我们说上来先要定校招层次,这个层次就按照中厂来讲。因为现在很多的双非一本目标都是在中厂。 这个同学有个实习经历,一本有八成的同学主项目都是重复的。HR他只能看到项目重不重复,要点对不对他不知道,就从这个角度来看,这位同学

洛谷P5490扫描线

0是最小的数字,将一个线段看成一个区间,对于一个矩形,从下扫到上,入边为1,而出边为-1,意思是将这个区间上的所有点加1(区间修改).把线段表示为Line[i],其中记录了l,r,h,tag,左右端点,高度,入边还是出边(1或-1) 那么每次区间修改后不为0的区间它的值可能是1,2,3或者是其它数字,这不好统计,可以将它转化一下,0是不是表示没有被覆盖过的地方,我们只要统计0的个数然后用总长减去