URAL1031
这道题是动态规划,我霸王硬上弓,写了个O(N4)的算法,居然WA啦。看讨论里有O(N)算法的解,想了半天没想出来。后来读的别人代码,唉,深感这是一道好题,我没有认真思考。
假设i为当前的车站,index1,index2,index3是与车站i的距离分别小于等于L1,L2,L3 最远的三个车站编号,则有动态规划公式:
prices(i)= min(prices(index1)+C1, prices(index2)+C2, prices(index3)+C3)
我觉得这个公式的推导比较复杂:
在最优解中,一旦在某车站A买了一张票,假设价格为C1,则可以用这张车票一直乘坐到离A的距离都小于等于L1的所有车站(结论1)。
由于“结论1”,可以证明距离目标车站A小于等于L1中最远的那个车站到A的价格,是所有距离A小于等于L1的车站中价格最小的(或与其它车站价格相同)(这个结论需要稍作思考,在此不赘述)。同理适用于L2,L3.所以对于距离A小于等于L3的所有车站,公式成立。
对与距离A大于L3的车站:假设距离A小于等于L3的最远车站为B,假设C到A的距离大于L3,则从C车站到B,要么价格相等,要么购买一张新票,所以prices(C) + prices(C,A)<=prices(C)+C3
从而可以得出推导公式。
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class URAL1031 {
static {
System.setIn(URAL1031.class.getResourceAsStream("/URAL1031.txt"));
}
private static PrintWriter stdout = new PrintWriter(System.out);
private static StreamTokenizer stdin = new StreamTokenizer(new InputStreamReader(System.in));
private static long L1;
private static long L2;
private static long L3;
private static long C1;
private static long C2;
private static long C3;
private static int N;
private static int M;
private static int START;
private static int END;
private static long[] distance;
private static long[][] prices;
/**
* @param args
*/
public static void main(String[] args) throws IOException {
readData();
cal();
}
private static void readData() throws IOException {
L1 = readInt();
L2 = readInt();
L3 = readInt();
C1 = readInt();
C2 = readInt();
C3 = readInt();
N = readInt();
START = readInt();
END = readInt();
if (START > END) {
int buf = START;
START = END;
END = buf;
}
START -= 1;//start from 0, not 1
END -= 1;
distance = new long[END - START + 1];
distance[0] = 0;
for (int i = 0; i < START - 1; i++) {
readInt();//ignore
}
int startDistance = readInt();
for (int i = 0; i < END - START; i++) {
int d = readInt();
distance[i + 1] = d - startDistance;
}
M = END - START + 1;
prices = new long[M][M];
for (int i = 0; i < M; i++) {
for (int j = i + 1; j < M; j++) {
prices[i][j] = calPrice(i, j);
prices[j][i] = prices[i][j];
}
}
}
private static void cal() {
//printMatrix();
for (int k = 2; k <= M - 1; k++) {
for (int i = 0; i < M; i++) {
for (int j = i + k; j < M; j++) {
long min = prices[i][j];
for (int x = i + 1; x < j; x++) {
long p = prices[i][x] + prices[x][j];
if (p < min) {
prices[i][j] = p;
prices[j][i] = p;
min = p;
}
}
}
}
}
//printMatrix();
stdout.println(prices[0][M - 1]);
stdout.flush();
}
private static int readInt() throws IOException {
stdin.nextToken();
return (int) stdin.nval;
}
private static long calDistance(int i, int j) {
long d = distance[j] - distance[i];
if (d < 0) {
return 0 - d;
} else {
return d;
}
}
private static long calPrice(int i, int j) {
if (i == j) {
return 0;
}
long d = calDistance(i, j);
if (d <= L1) {
return C1;
} else if (d <= L2) {
return C2;
} else if (d <= L3) {
return C3;
}
return Integer.MAX_VALUE;
}
private static void printMatrix() {
System.out.print(" ");
for (int i = 0; i < M; i++) {
System.out.print(t(i));
}
System.out.println();
for (int i = 0; i < M; i++) {
System.out.print(t(i));
for (int j = 0; j < M; j++) {
System.out.print(t(prices[i][j]));
}
System.out.println();
}
}
private static String t(long i) {
if (i >= Integer.MAX_VALUE) {
return " ";
}
if (i < 10) {
return " " + i;
} else if (i >= 10 && i <= 99) {
return " " + i;
}
return " " + i;
}
}