草庐IT

[IOI2000]邮局 题解

xiaoxiexie's blog 2023-03-28 原文

简要题意

线段上有 \(V\) 个村庄,现在要建 \(P\) 个邮局,使每个村庄到最近的邮局的距离之和最小。

50分做法

\(dp[i][j]\) 表示第一个村庄到第 \(i\) 个村庄,建了 \(j\) 个邮局的最小距离,不难得出状态转移方程:
\(dp[i][j]=min(dp[k][j-1]+w[k+1][i])\)
其中 \(w[i][j]\) 表示在第 \(i\)\(j\) 个村庄之间建一个邮局的最短总距离。
根据初中知识不难求得,邮局建在第 \(i\)\(j\) 个村庄的中位数的位置上(奇数个村庄)或第 \(i\)\(j\) 个村庄的两个中位数之间(偶数个村庄),则总距离最短,因此我们可以递推求出 \(w[i][j]\)\(w[i][j]=\begin{cases} & 0\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ } i=j \\ & w[i][j-1]+v[j]-v[(i+j)/2] \text{ }\text{ }\text{ }\text{ }\text{ }i<j\end{cases} \text{ }\) ,其中 \(v[i]\) 表示第 \(i\) 个村庄的位置。

证明:

当第 \(i\)\(j\) 个村庄为奇数个时,第 \(i\)\(j-1\) 个村庄为偶数个,第 \(i\)\(j-1\) 个村庄的中位数为第 \(\left \lfloor \frac{(i+j-1)}{2} \right \rfloor\) 个村庄和第 \(\left \lceil \frac{(i+j-1)}{2} \right \rceil\) 个村庄,第 \(i\)\(j\) 个村庄的中位数为第 \(\frac{(i+j)}{2}\)\(\left \lceil \frac{(i+j-1)}{2} \right \rceil\) 个村庄;
当第 \(i\)\(j\) 个村庄为偶数个时,第 \(i\)\(j-1\) 个村庄为奇数个,第 \(i\)\(j-1\) 个村庄的中位数为第 \(\frac{(i+j-1)}{2}\) 个村庄,第 \(i\)\(j\) 个村庄的中位数为第 \(\left \lfloor \frac{(i+j)}{2} \right \rfloor\)\(\frac{(i+j-1)}{2}\) 个村庄和第 \(\left \lceil \frac{(i+j)}{2} \right \rceil\) 个村庄;
此时第 \(i\)\(j-1\) 个村庄到邮局的距离之和不变,第 \(j\) 个村庄到邮局的距离即第 \(j\) 个村庄到第 \(i\)\(j\) 个村庄的中位数的距离,即第 \(j\) 个村庄的位置减去第 \(i\)\(j\) 个村庄的中位数的位置。

预处理 \(w[i][j]\) 之后,我们可以三层循环分别枚举 \(i,j,k\),时间复杂度为 \(O(V^{2}P)\) ,无法通过大数据。

满分做法

这是一道DP数组二维的区间DP,并且状态转移方程为 \(dp[i][j]=dp[i][k]+dp[k+1][j]+w[i][j]\) 的形式,因此考虑四边形不等式优化。

四边形不等式

定义:

如果对于任意的 \(A\leq B\leq C\leq D\),均满足 \(w[A][C]+w[B][D]\leq w[A][D]+w[B][C]\),则称 \(w\) 满足四边形不等式。

证明:

在这一题中,根据 \(w[i][j]\) 的递推式,可得
\(\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }w[i][j+1]-w[i][j]=v[j+1]-v[(i+j+1)/2]\)
\(\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }w[i+1][j+1]-w[i+1][j]=v[j+1]-v[(i+j+2)/2]\)
两者相减,得
\(\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }w[i][j+1]-w[i][j]-(w[i+1][j+1]-w[i+1][j])\)
\(\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }=v[j+1]-v[(i+j+1)/2]-(v[j+1]-v[(i+j+2)/2])\)
\(\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }=v[j+1]-v[(i+j+1)/2]-v[j+1]+v[(i+j+2)/2]\)
\(\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }=v[(i+j+2)/2]-v[(i+j+1)/2]\geq 0\)

\(\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }w[i][j+1]-w[i][j]-(w[i+1][j+1]-w[i+1][j])\geq 0\)
\(\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }w[i][j+1]-w[i][j]-w[i+1][j+1]+w[i+1][j]\geq 0\)
\(\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }w[i][j]+w[i+1][j+1]\leq w[i][j+1]+w[i+1][j]\)
\(w\) 满足四边形不等式,则 \(dp\) 同样满足四边形不等式,设 \(s[i][j]\)\(dp[i][j]\) 的最优决策点 \(k\),可得\(s[i][j]\)单调,即\(s[i][j]\leq s[i][j+1]\leq s[i+1][j+1]\)\(s[i][j-1]\leq s[i][j]\leq s[i+1][j]\)(这一点的证明后面会提到),每次让 \(k\)\(s[i][j-1]\)\(s[i+1][j]\) 的范围内枚举,就将原本 \(O(V^{2}P)\) 的DP变为 \(O(VP)\) 的了,可以AC,注意此时 \(i\) 需要倒着枚举,因为需要用到 \(s[i+1][j]\)

\(s[i][j-1]\leq s[i][j]\leq s[i+1][j]\) 的证明

假设状态规划方程是 \(dp[i][j]=dp[i][k]+dp[k+1][j]+w[i][j]\) 的形式,设 \(y\) 为使 \(dp[i][j-1]\) 最小的 \(k\),即 \(s[i][j-1]\),令 \(x<y\),有 \(x+1\leq y+1\leq j-1<j\),根据四边形不等式,得
\(\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }dp[x+1][j-1]+dp[y+1][j]<=dp[y+1][j-1]+dp[x+1][j]\)

\(\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }dp[i][x]+dp[x+1][j-1]+w[i][j-1]+dp[i][y]+dp[y+1][j]+w[i][j] <=\)
\(\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ } dp[i][x]+dp[x+1][j]+w[i][j]+dp[i][y]+dp[y+1][j-1]+w[i][j-1]\)

\(\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }dp[i][j-1](k=x)+dp[i][j](k=y)<=dp[i][j](k=x)+dp[i][j-1](k=y)\)
\(\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }\text{ }dp[i][j-1](k=x)-dp[i][j-1](k=y)<=dp[i][j](k=x)-dp[i][j](k=y)\)
不等式左右两边显然都大于0(\(y\) 是最优决策点,\(dp[i][j]\) 的值最小),所以 \(dp[i][j]\) 的最优决策点一定不是任意一个 \(x\),即 \(s[i][j]\geq s[i][j-1]\)(即 \(y\)),同理可证\(s[i][j]\leq s[i+1][j]\)

细节

  • 在预处理前需要对 \(v\) 进行排序,保证 \(v[i]\) 的单调(递增)性,否则 \(w[i][j]\) 就不满足四边形不等式,也就无法使用四边形不等式优化了,然而这题数据较水,给出的 \(v[i]\) 本身就是单调递增的,无需排序(别问我怎么知道的)。
  • DP数组要初始化成INF,且\(dp[i][1]=w[1][i]\),DP时 \(j\)\(2\) 开始枚举,否则会使用 \(s[i][0]\)\(dp[k][0]\)
  • 注意 \(s\) 的边界值:\(s[i][1]=1\)(只建1个邮局时最佳划分点只能是第一个村庄),\(s[v+1][i]=v-1\)(倒序枚举 \(dp[i][j]\) 中的 \(i\)\(v-1\) 即最佳决策点 \(k\) 范围的初始值)。

代码

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
int v,p,a[3005],w[3005][3005],f[3005][3005],s[3005][3005],i,j,k;
int main()
{
	ios::sync_with_stdio(false);
	cin>>v>>p;
	for(i=1;i<=v;++i)cin>>a[i];//输入
	//这里本应有sort,但是本题数据过水,a[i]本来就单调递增
	for(i=1;i<v;++i)
		for(j=i+1;j<=v;++j)
			w[i][j]=w[i][j-1]+a[j]-a[i+j>>1];//预处理w[i][j]
	//下面几行都是预处理
	for(i=1;i<=v;++i)
		for(j=1;j<=p;++j)f[i][j]=INF;
	for(i=1;i<=v;++i)f[i][1]=w[1][i],s[i][1]=1;
	for(i=1;i<=p;++i)s[v+1][i]=v-1;
	//上面几行都是预处理
	for(i=2;i<=p;++i)//枚举邮局数
		for(j=v;j>=i;j--)//倒序枚举村庄
			for(k=s[j][i-1];k<=s[j+1][i];++k)//四边形不等式优化
				if(f[k][i-1]+w[k+1][j]<f[j][i])
					f[j][i]=f[k][i-1]+w[k+1][j],s[j][i]=k;//记得更新最优决策点
	cout<<f[v][p]<<endl;
	return 0;
}

有关[IOI2000]邮局 题解的更多相关文章

  1. 【算法题解】20. 两数之和 - 2

    这是一道简单题题目来自:https://leetcode.cn/problems/two-sum/题目给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。提示:22nums.length104−109−109nums[i]109−109−109target109只会存在一个有效答案进阶:你可以想出一个时间复杂度小于O(n2)O(n^2)O(n2)的算法吗?示例1:输入:nums=[2,7,11,15],targe

  2. javascript - 在 Javascript 中快速检查 2000 个复选框的方法? - 2

    我有一个网页,上面有几千个复选框,我想添加一个“全部选中”功能。不幸的是,我当前的实现使GoogleChrome挂起至少五秒钟。这是我尝试过的(使用jQuery):$('input').attr('checked',true);//aswellas...$('input').click();我相信实际的Javascript运行速度很快,但是浏览器可能无法如此快速地呈现所有更新。我可以做点别的吗?这是一个简化的例子:https://www.msu.edu/~weinjare/checkboxes.html我还运行了Chrome内置的分析器并得到了这些结果: 最

  3. javascript - Date.parse(0) 返回 2000 年午夜,为什么? - 2

    当我尝试Date.parse()一个整数或字符串0时,它返回946681200000,转换为以下日期:2000年1月1日星期六00:00:00GMT+0100(CET)为什么?我会假设解析器将单个零解释为2000年,但规范没有说明单字符年份定义-RFC2822和ISO8601要求字符串中包含四个字符的年份。我想更好地理解字符串“0”是如何被解析为一个日期的,为什么它被接受为一个有效的日期(它不应该是NaN或类似的吗?)以及为什么选择2000年而不是例如1900年。更新经过反复试验,我发现单个数字实际上在不同的数字范围内有不同的解释。0-12:2000年的一个月13-31:NaN32-4

  4. 蓝桥杯第十四届省赛完整题解 C/C++ B组 - 2

    没有测评,不知道对不对,仅仅过样例而已试题A:日期统计本题总分:5分【问题描述】小蓝现在有一个长度为100的数组,数组中的每个元素的值都在0到9的范围之内。数组中的元素从左至右如下所示:5686916124919823647759503875815861830379270588570991944686338516346707827689565614010094809128502533现在他想要从这个数组中寻找一些满足以下条件的子序列:   1.子序列的长度为8;   2.这个子序列可以按照下标顺序组成一个yyyymmdd格式的日期,并且要求这个日期是2023年中的某一天的日期,例如202309

  5. 2023第十四届蓝桥杯C/C++B组省赛题解 - 2

    2023蓝桥C/C++B组省赛文章目录2023蓝桥C/C++B组省赛试题A:日期统计题目描述枚举参考代码试题B:01串的熵题目描述枚举|模拟参考代码试题C:冶炼金属题意描述取交集参考代码试题D:飞机降落题意描述DFS+剪枝,懒得写试题E:接龙数列题意描述DP参考代码试题F:岛屿个数题意描述dfs|连通块参考代码试题G:子串简写题意描述前缀和参考代码试题H:整数删除题意描述双向链表|最小堆参考代码试题I:景区导游题意描述带权LCA参考代码试题J:砍树题意描述树上差分参考代码试题A:日期统计题目描述【问题描述】小蓝现在有一个长度为100的数组,数组中的每个元素的值都在0到9的范围之内。数组中的元素

  6. javascript - angular.js - 解析 html 函数需要 2000 毫秒甚至更多 - 2

    关闭。这个问题需要debuggingdetails.它目前不接受答案。编辑问题以包含desiredbehavior,aspecificproblemorerror,andtheshortestcodenecessarytoreproducetheproblem.这将有助于其他人回答问题。关闭7年前。Improvethisquestion我正在尝试加速我的网站。这是我在Timeline/ProfileJS内的chrome开发人员工具中找到的。其中包含大约150个蓝色的ParseHTML(在屏幕中)。这是加载时间的50%。我使用平板电脑对其进行了测试,该功能甚至花费了15000毫秒!我正在

  7. Windows 2000虚拟机安装全过程(VMware) - 2

    目录1.下载安装VMware 2.安装设置Windows2000由于一次意外,我发现了一本很旧很旧的旧书,上面的编程示例都是以Windows2000来举例子的(哪本书用win2000?emm……)。我原本想给电脑重装Windows2000,但又舍不得现在的Win11,又是一次意外(怎么这么多意外),我发现了一个神奇的虚拟机软件——VMware,据说它可以一个软件安装所有虚拟机系统(如Windows,Linux,macOS……),这不就可以用它来安装Windows2000啦!废话不多说,马上开始~------------------------------------正文------------

  8. LeetCode——链表简单题题解 - 2

    83.删除排序链表中的重复元素题目描述给定一个已排序的链表的头head,删除所有重复的元素,使每个元素只出现一次。返回已排序的链表。输入:head=[1,1,2]输出:[1,2]解题思路:用一个指向节点类型的指针保存头结点,用另一个指向节点类型的指针对该链表进行遍历,由于是有序的,当出现不同的值就说明不会再出现跟前面的值相同的节点了,最后循环结束的条件是遍历到最后一个节点的时候,也就是该节点的next指向空的时候,停止循环,返回该保存的头结点,另外,如果传过来的头结点是空,则直接返回空。参考代码:/***Definitionforsingly-linkedlist.*structListNod

  9. C# XPathSelectElement 和 xml with attribute xmlns ="http://www.w3.org/2000/09/xmldsig#"Help - 2

    我需要读取一个具有属性xmlns="http://www.w3.org/2000/09/xmldsig#"的xml元素。XPathSelectElement给出错误“对象引用未设置到对象的实例。”这是示例代码。varxml="TagATagB";XDocumentxd=XDocument.Parse(xml);varstr=xd.XPathSelectElement("/root/tagB").ToString(SaveOptions.DisableFormatting);Console.WriteLine(str);上面代码的结果是:TagB如果我输入属性,varxml="TagAT

  10. NEUQ week 12 题解 - 2

    P1776宝物筛选宝物筛选题目描述终于,破解了千年的难题。小FF找到了王室的宝物室,里面堆满了无数价值连城的宝物。这下小FF可发财了,嘎嘎。但是这里的宝物实在是太多了,小FF的采集车似乎装不下那么多宝物。看来小FF只能含泪舍弃其中的一部分宝物了。小FF对洞穴里的宝物进行了整理,他发现每样宝物都有一件或者多件。他粗略估算了下每样宝物的价值,之后开始了宝物筛选工作:小FF有一个最大载重为WWW的采集车,洞穴里总共有nnn种宝物,每种宝物的价值为viv_ivi​,重量为wiw_iwi​,每种宝物有mim_imi​件。小FF希望在采集车不超载的前提下,选择一些宝物装进采集车,使得它们的价值和最大。输入

随机推荐