3-23 有向直线m中值问题
问题描述
给定一条有向直线L以及L上的n+1个点x0<x1<...<xnx0<x1<...<xn。有向直线L上的每个点xixi都有一个权w(xi)w(xi);每条有向边(xi,xi−1)(xi,xi−1)也都有一个非负边长d(xi,xi−1)d(xi,xi−1)。有向直线L上的每个点xixi可以看作客户,其服务需求量为w(xi)w(xi)。每条边(xi,xi−1)(xi,xi−1)的边长d(xi,xi−1)d(xi,xi−1)可以看作运输费用。如果在点 xixi 处未设置服务机构,则将点 xixi 处的服务需求沿有向边转移到点 xjxj 处服务机构需付出的服务转移费用为w(xi)∗d(xi,xj)w(xi)∗d(xi,xj)。在点x0 处已设置了服务机构,现在要在直线 L 上增设 k 处服务机构,使得整体服务转移费用最小。
对于给定的有向直线 L,编程计算在直线 L 上增设 k 处服务机构的最小服务转移费用。
数据输入:
第 1 行有 1 个正整数 n,表示有向直线 L 上除了点 x0x0 外还有n个点x0<x1<...<xnx0<x1<...<xn。接下来的n行中,每行有2个整数。第i+1行的2个整数分别表示 w(xn−i−1)w(xn−i−1) 和 d(xn−i−1,xn−i−2)d(xn−i−1,xn−i−2) 。
Java: version 1
import java.util.Scanner;
public class YouXiangZhiXianMZhongZhi {
private static int n,m;
private static int[] dist,wt,swt;
private static int[][] minco;
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int d,w;
while (true){
n = input.nextInt();
m = input.nextInt();
dist = new int[n+2];
wt = new int[n+1];
swt = new int[n+1];
minco = new int[n+1][m+1];
dist[1] = 0;
wt[0] = 0;
swt[1] = 0;
wt[1] = input.nextInt();
dist[2] = input.nextInt();
for(int i=2; i<=n; i++){
w = input.nextInt();
d = input.nextInt();
wt[i] = wt[i-1] + w;
dist[i+1] = dist[i] + d;
swt[i] = swt[i-1] + w * dist[i];
}
comp();
System.out.println(minco[n][m]);
}
}
private static void comp(){
int i,j,k,tmp;
for(i=1; i<=n; i++)
minco[i][0] = getw(0,i+1);
for(i=1; i<=n; i++)
for(j=1; j<=m; j++){
if(j >= i)
minco[i][j] = 0;
else{
minco[i][j] = getw(1,i+1);
for(k=2; k<=i; k++){
tmp = minco[k-1][j-1] + getw(k,i+1);
if(tmp < minco[i][j])
minco[i][j] = tmp;
}
}
}
}
private static int getw(int i, int j){
if(i > j)
return 0;
else
return (wt[j-1] - wt[i]) * dist[j] - (swt[j-1] - swt[i]);
}
}
Java: version 2
import java.util.Scanner;
public class YouXiangZhiXianMZhongZhi1 {
private static int n,m;
private static int[] dist,wt,swt;
private static int[] minco;
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int d,w;
while (true){
n = input.nextInt();
m = input.nextInt();
dist = new int[n+2];
wt = new int[n+1];
swt = new int[n+1];
minco = new int[n+1];
dist[1] = 0;
wt[0] = 0;
swt[1] = 0;
wt[1] = input.nextInt();
dist[2] = input.nextInt();
for(int i=2; i<=n; i++){
w = input.nextInt();
d = input.nextInt();
wt[i] = wt[i-1] + w;
dist[i+1] = dist[i] + d;
swt[i] = swt[i-1] + w * dist[i];
}
comp();
System.out.println(minco[n]);
}
}
private static void comp(){
int i,j,k,tmp;
for(i=1; i<=n; i++)
minco[i] = getw(0,i+1);
for(j=1; j<=m; j++){
for(i=n; i>j; i--){
minco[i] = getw(1,i+1);
for(k=2; k<=i; k++){
tmp = minco[k-1] + getw(k,i+1);
if(tmp < minco[i])
minco[i] = tmp;
}
}
for(i=1; i<=j; i++)
minco[i] = 0;
}
}
private static int getw(int i, int j){
if(i > j)
return 0;
else
return (wt[j-1] - wt[i]) * dist[j] - (swt[j-1] - swt[i]);
}
}
Input & Output
9 2
1 2
2 1
3 3
1 1
3 2
1 6
2 1
1 2
1 1
26
Reference
王晓东《计算机算法设计与分析》(第3版)P98

这篇博客探讨了有向直线m中值问题,其中涉及到如何在一条有向直线上设置k个服务机构,以最小化服务转移费用。问题描述包括点的权值、边的长度和服务需求转移费用。文章提供了两个Java版本的实现,并给出了数据输入格式。
3288





