Post Office--邮局问题(动态规划)

Post Office

Description
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 are no two villages in the same position. The distance between two positions is the absolute value of the difference of their integer coordinates.
Post offices will be built in some, but not necessarily all of the villages. A village and the post office in it have the same position. For building the post offices, their positions should be chosen so that the total sum of all distances between each village and its nearest post office is minimum.
You are to write a program which, given the positions of the villages and the number of post offices, computes the least possible sum of all distances between each village and its nearest post office.

Input
Your program is to read from standard input. The first line contains two integers: the first is the number of villages V, 1≤V≤300, and the second is the number of post offices P, 1≤P≤30, P≤V. The second line contains V integers in increasing order. These V integers are the positions of the villages. For each position X it holds that 1≤X≤10000.

Output
The first line contains one integer S, which is the sum of all distances between each village and its nearest post office.

Samples
Input 复制
10 5
1 2 3 6 7 9 11 22 44 50
Output
9

题目大意
有几个村庄,然后准备挑几个出来建邮局,村庄的位置在一个数轴上,要使村庄到离他们最近的邮局的总距离最短,想出方案,输出最短的距离。

思路:
假设n个村庄,建k个,那么我们转换成已经建成k-1个最小了,再在剩下的选一个建立最小距离和。

用两个数组来记录:
f[i][j] :是1-i个村庄,建立了j个邮局的最小消费
w[i][j]:是i-j村庄建立一个邮局的最小消费

这里求w数组优化需要来理解一下:
如果原本i和j之间有偶数个village,假设此时post office的修建地址设置为中位数中较大的数的位置,此时新加入i后,post office的位置不发生改变,那么仍然由如下计算公式:
w[i,j] =w[i,j-1]+a[i] - a[(j+i)/2]
·如果原本i和j之间有奇数个village(即(i+j)%2==0),新加入一个j之后,仍然可以取原来的K作为中位数,此时中位数位置不变,所以
w[i,j] = w[i,j-1]+a[i] - a[(j+i)/2]

这里附图理解一下
在这里插入图片描述

所以优化后的 w[i,j] = w[i,j-1]+a[i] - a[(j+i)/2]

最后最后的f数组转移方程:
dp[i][j]=min(dp[i][j],dp[k][j-1]+w[k+1][i]);

AC代码:

int a[maxn];
int w[400][400],dp[400][400];
int main(){
	int n = read() , m = read();
	for(int i=1;i<=n;i++) cin>>a[i];//输入位置,他本身就是前缀和
	for(int i=1;i<=n;i++){
		for(int j=1+i;j<=n;j++){
			w[i][j]=w[i][j-1]+a[j]-a[(i+j)/2];
		}
	} 
	memset(dp,0x3f3f3f3f,sizeof(dp));
	for(int i=1;i<=n;i++) dp[i][i]=0,dp[i][1]=w[1][i];//当只建立一个邮局时是相等的
	for(int i=1;i<=n;i++){
		for(int j=2;j<=min(m,i);j++){//邮局个数 
		//dp[i][j]=inf;
		for(int k=j;k<=i-1;k++){//枚举可转移的位置,当然比邮局个数大 
                    dp[i][j]=min(dp[i][j],dp[k][j-1]+w[k+1][i]);
                }
		}
	}
	cout<<n<<" "<<m<<" "<<dp[n][m]<<"\n"; 
	for(int i=1;i<=n;i++) cout<<a[i]<<" ";
}

不懂的可以直接问啊

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: swustoj493: postoffice 这个问题不是很清楚,不知道您想要什么样的回答。如果您是想问西南科技大学的oj系统中的题目编号为swustoj493的题目是什么,那么这道题目是关于模拟邮局的题目,需要模拟邮局的业务流程,包括寄信、收信、查询等操作。如果您有其他问题,请具体说明。 ### 回答2: swustoj493是一个在线评测系统,主要用于程序设计竞赛和编程练习。其中postoffice是一道题目,大致描述如下: 假设你现在是一个邮差,需要给不同地点的人分发信件。你可以驾驶一辆汽车,汽车每次可以行驶d距离,需要从邮局出发,然后依次到达所有的收件人所在的位置,最终回到邮局。每个收件人的位置以及他们的信息都已知,你需要根据他们的需求,按照最优的顺序依次分配邮件,保证每个人都能及时收到自己的信件。 这个问题实际上是TSP问题(旅行售货员问题)的一种变体。TSP问题的目标是找到一条路径,使得经过所有的点并回到起点,总路程最短。而postoffice问题则是在TSP问题的基础上增加了一些限制,使得问题更加复杂。 解决这个问题的方法主要有两种:暴力枚举和近似算法。暴力枚举法可以穷尽所有可能的路径,但时间复杂度会随着点数的增加呈指数级增长,不适合应用于大规模数据。而近似算法则可以在合理的时间内快速求解问题,但得到的路径并不一定是最优解。 在编程实现时,可以采用图论的思路,利用邻接矩阵或邻接表来表示点之间的关系,然后使用动态规划、贪心等算法来求解。此外,还可以结合优化算法如模拟退火、遗传算法、粒子群优化等来进一步提高算法的效率。 总的来说,postoffice问题是一个难度较高的数学问题,需要较高的抽象思维、编程技巧以及优化算法知识,同时也是一个很好的练手题目。 ### 回答3: SWUSTOJ493: postoffice是一个计算机程序设计考试题目,该题目是一个基于图论算法问题。题目描述如下: 你的任务是帮助快递公司规划一条最短的路线,使得每个邮局都可以被访问到。假设有$n$个邮局和$m$条道路,每个邮局有一个编号$1\sim n$,并且每个道路有一个长度$l_i$,连接着两个邮局$x_i$和$y_i$。 为了简化问题,我们假设每个道路都是双向的,且两个邮局之间只有一条道路相连。快递员可以从任一邮局出发,但必须返回原始的起点才算完成任务。 你需要设计一个算法来寻找一条最短的路线,使得经过的邮局数量最大,输出所经过的邮局数量即可。 对于这道题目,我们可以采用Dijkstra算法,首先将所有的邮局看作一个个节点,然后建立邮局之间的道路连接,根据Dijkstra算法的特点,每次会寻找距离起点最近的节点,我们可以在算法的过程中记录下它经过的邮局数量,最终输出经过邮局数量最大的那条路径及经过的邮局数量即可。 例如,在图中点集为$V=\{1,2,3,4,5\}$,边集为$E=\{(1,2,1),(1,3,2),(2,3,2),(2,4,3),(2,5,5),(3,5,4),(4,5,1)\}$,其中(1,2,1)表示点1和点2之间有一条长度为1的边,求所经过的邮局数量最大的最短路经过的邮局数量为3,即起点到达2、3、5这三个节点。 因此,对于SWUSTOJ493: postoffice考试题目,我们只需要利用Dijkstra算法,按照题目要求,记录经过的邮局数量最大的路径即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值