题意:
租了一俩车从城市A到城市B,开始有100L油,油箱总共可以装200L油,行驶1KM要1L油,路上有加油站,离A有不同的距离,每升油价格不同。
问,到城市B油箱还有100L油,最少的花费是多少。
dp[i][j] 表示在站点 i 有油 j 时的最小花费。那么
dp[i][j] = min(dp[i-1][j+d[i]],dp[i][j]),d[i] 表示 i-1到i的距离。
dp[i][j]有俩个来源,一个是从dp[i-1][j+d[i]],dp[i][j]表示在站点i加油到j 的花费。
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Main
{
static Scanner scanner;
final static int G = 110;
// final static int G = 8;
final static int T = 206;
// final static int N = 5;
// dij表示在i站点gas是j的时候最小花费
static int[][] dp = new int[G][T];
static int dis;
static int[] sd = new int[G];
static int[] sp = new int[G];
static int[] disSum = new int[G];
static int gt;
static int INF = Integer.MAX_VALUE;
static int maxDis = -1;
static int tt = 1;
public static void main(String[] args) throws FileNotFoundException
{
scanner = new Scanner(System.in);
//scanner = new Scanner(new File("/Users/caicai/in"));
String str = scanner.nextLine();
int val = Integer.valueOf(str);
// empty line
tt = 1;
while (val-- != 0)
{
gt = 1;
maxDis=-1;
dis = scanner.nextInt();
sd[0] = 0;
sp[0] = 0;
int preDis = 0;
str = scanner.nextLine();
while (scanner.hasNextLine())
{
// split
str = scanner.nextLine();
if (str.isEmpty())
{
break;
}
ByteArrayInputStream si = new ByteArrayInputStream(str.getBytes());
Scanner scanner2 = new Scanner(si);
int diss = scanner2.nextInt();
int price = scanner2.nextInt();
scanner2.close();
if (diss > dis) continue;
sd[gt] = diss - preDis;
preDis = diss;
sp[gt] = price;
++gt;
if (diss > maxDis) maxDis = diss;
}
// dp
dp();
}
}
static void init()
{
for (int i = 0; i < G; i++)
{
for (int j = 0; j < T; j++)
{
if (i == 0 || j == 0) dp[i][j] = INF - 1;
else
dp[i][j] = INF;
}
}
}
static void dp()
{
init();
if (sd[1] > 100)
{
if (tt != 1) System.out.println();
System.out.println("Impossible");
++tt;
return;
}
dp[1][100 - sd[1]] = 0;
// 多余的gas
int h = 100 - sd[1];
for (int i = h; i >= 0; i--)
{
dp[1][i] = (h - i) * -1 * sp[1];
}
for (int i = 1; i < gt; i++)
{
for (int j = 0; j <= 200; j++)
{
// 当前的站点gas是j
int diss = sd[i];
if (diss + j > 200 || dp[i - 1][diss + j] == INF)
{
continue;
}
dp[i][j] = Math.min(dp[i - 1][diss + j], dp[i][j]);
for (int k = j + 1; k <= 200; k++)
{
// 当前站点加到k气要的钱
int curPrice = sp[i] * (k - j) + dp[i][j];
dp[i][k] = Math.min(dp[i][k], curPrice);
// if (diss + k > 200) continue;
// int preCurPrice = dp[i - 1][diss + k];
// dp[i][k] = Math.min(dp[i][k], preCurPrice);
}
}
}
// check val
int half = 100;
// 检查最后一个站点
int lastDis = dis - maxDis;
int gas = lastDis + half;
if (gas > 200 || dp[gt - 1][gas] == INF)
{
if (tt != 1) System.out.println();
System.out.println("Impossible");
++tt;
return;
}
else
{
if (tt != 1) System.out.println();
++tt;
System.out.println(dp[gt - 1][gas]);
}
}
}