在一个按照南北方向划分成规整街区的城市里,n 个居民点分布在一条直线上的 n 个坐标点 x1<x2<...<xn x 1 < x 2 < . . . < x n 处。居民们希望在城市中至少选择1个,但不超过k个居民点建立服务机构。在每个居民点 xi x i 处,服务需求量为 wi>=0 w i >= 0 ,在该居民点设置服务机构的费用为 ci>=0 c i >= 0 。 假设居民点 xi x i 到距其最近的服务机构的距离为 di d i ,则居民点xi的服务费用为 wi×di w i × d i 。
建立 k 个服务机构的总费用为 A+B。A 是在 k 个居民点设置服务机构的费用的总和;B 是 n 个居民点服务费用的总和。
对于给定直线L上的n个点 x1<x2<...<xn x 1 < x 2 < . . . < x n ,编程计算在直线L上最多设置k处服务机构的最小总费用。
数据输入:
第 1 行有 2 个正整数 n 和 k。n 表示直线 L 上有 n 个点 x1<x2<...<xn x 1 < x 2 < . . . < x n ; k是服务机构总数的上限。接下来的n行中,每行有3个整数。第i+1行的3个整数 xi x i , wi w i , ci c i ,分别表示相应居民点的位置坐标,服务需求量和在该点设置服务机构的费用。
import java.util.Scanner;
public class ZhiXianKZhongZhi {
private static int n,m;
private static int[] wt,swt,x,c,ww,dist;
private static int[][] opt1,opt2;
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int w;
while (true){
n = input.nextInt();
m = input.nextInt();
wt = new int[n+1];
swt = new int[n+1];
x = new int[n+1];
c = new int[n+1];
ww = new int[n+1];
dist = new int[n+1];
opt1 = new int[m+1][n+1];
opt2 = new int[m+1][n+1];
wt[0] = 0;
swt[0] = 0;
for(int i=1; i<=n; i++){
x[i] = input.nextInt();
w = input.nextInt();
c[i] = input.nextInt();
ww[i] = w;
wt[i] = wt[i-1] + w;
dist[i] = x[i] - x[1];
swt[i] = swt[i-1] + w * dist[i];
}
comp();
System.out.println(solution());
}
}
private static int solution(){
int tmp = opt1[1][n];
for(int i=2; i<=m; i++)
if(opt1[i][n] < tmp)
tmp = opt1[i][n];
return tmp;
}
private static void comp(){
int i,j,k,tmp;
for(j=1; j<=n; j++)
opt2[1][j] = c[j] + getw2(0,j);
for(j=1; j<=n; j++) {
opt1[1][j] = opt2[1][1] + getw1(1,j);
for(k=2; k<=j; k++){
tmp = opt2[1][k] + getw1(k,j);
if(opt1[1][j] > tmp)
opt1[1][j] = tmp;
}
}
for(i=2; i<=m; i++){
for(j=i; j<=n; j++){
opt2[i][j] = opt1[i-1][i-1] + getw2(i-1,j);
for(k=i; k1][k] + getw2(k,j);
if(opt2[i][j] > tmp)
opt2[i][j] = tmp;
}
opt2[i][j] += c[j];
}
for(j=i; j<=n; j++){
opt1[i][j] = opt2[i][i] + getw1(i,j);
for(k=i+1; k<=j; k++){
tmp = opt2[i][k] + getw1(k,j);
if(opt1[i][j] > tmp)
opt1[i][j] = tmp;
}
}
}
}
private static int getw1(int j, int m){
return (swt[m] - swt[j]) - (wt[m] - wt[j]) * dist[j];
}
private static int getw2(int j, int m){
return (wt[m-1] - wt[j]) * dist[m] - (swt[m-1] - swt[j]);
}
}
import java.util.Scanner;
public class ZhiXianKZhongZhi1 {
private static int n,m;
private static int[] wt,swt,x,c,ww,dist;
private static int[] opt1,opt2;
private static int min;
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int w;
while (true){
n = input.nextInt();
m = input.nextInt();
wt = new int[n+1];
swt = new int[n+1];
x = new int[n+1];
c = new int[n+1];
ww = new int[n+1];
dist = new int[n+1];
opt1 = new int[n+1];
opt2 = new int[n+1];
wt[0] = 0;
swt[0] = 0;
for(int i=1; i<=n; i++){
x[i] = input.nextInt();
w = input.nextInt();
c[i] = input.nextInt();
ww[i] = w;
wt[i] = wt[i-1] + w;
dist[i] = x[i] - x[1];
swt[i] = swt[i-1] + w * dist[i];
}
comp();
System.out.println(min);
}
}
private static void comp(){
int i,j,k,tmp;
for(j=1; j<=n; j++)
opt2[j] = c[j] + getw2(0,j);
for(j=1; j<=n; j++) {
opt1[j] = opt2[1] + getw1(1,j);
for(k=2; k<=j; k++){
tmp = opt2[k] + getw1(k,j);
if(opt1[j] > tmp)
opt1[j] = tmp;
}
}
min = opt1[n];
for(i=2; i<=m; i++){
for(j=i; j<=n; j++){
opt2[j] = opt1[i-1] + getw2(i-1,j);
for(k=i; kif(opt2[j] > tmp)
opt2[j] = tmp;
}
opt2[j] += c[j];
}
for(j=i; j<=n; j++){
opt1[j] = opt2[i] + getw1(i,j);
for(k=i+1; k<=j; k++){
tmp = opt2[k] + getw1(k,j);
if(opt1[j] > tmp)
opt1[j] = tmp;
}
}
if(opt1[n] < min)
min = opt1[n];
}
}
private static int getw1(int j, int m){
return (swt[m] - swt[j]) - (wt[m] - wt[j]) * dist[j];
}
private static int getw2(int j, int m){
return (wt[m-1] - wt[j]) * dist[m] - (swt[m-1] - swt[j]);
}
}
9 3
2 1 2
3 2 1
6 3 3
7 1 1
9 3 2
15 1 6
16 2 1
18 1 2
19 1 1
19
王晓东《计算机算法设计与分析》(第3版)P99-100