大意不再赘述。
思路:d[i][j]表示到第i个加油站时,车厢内剩余油量为j时的最小消耗。
从i-1站到i站,要满足j+A[i].dis-A[j].dis <= 200且d[i][j] = d[i-1][j+A[i].dis-A[j].dis],对于当前站点的决策,即加油的最优值,k从0开始循环,保证j+k<=200即可,题目不保证加油站的距离一定比终点小,所以我们只截取距离<=de的加油站。取最大值时保证可以从最后一个加油站到达终点。即i >= 100+de-A[n].dis即可。
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 110;
const int INF = 0x3f3f3f3f;
struct
{
int dis, price;
}A[MAXN];
int n;
int de;
int d[110][210];
void init()
{
n = 1;
for(int i = 0; i < 110; i++)
for(int j = 0; j < 210; j++)
d[i][j] = INF;
d[0][100] = 0;
}
int dp()
{
for(int i = 1; i <= n; i++)
{
for(int j = 0; j <= 200; j++)
{
if(j + A[i].dis - A[i-1].dis <= 200)
{
int &st = d[i-1][j + A[i].dis - A[i-1].dis];
for(int k = 0; j+k <= 200; k++)
{
d[i][j+k] = min(d[i][j+k], st+k*A[i].price);
}
}
}
}
int ans = INF;
for(int i = 100; i <= 200; i++)
{
if(i >= (100 + de - A[n].dis) && d[n][i] < ans) ans = d[n][i];
}
return ans;
}
void read_case()
{
char str[110];
scanf("%d%*c", &de);
while(gets(str))
{
if(str[0] == '\0') break;
sscanf(str, "%d%d", &A[n].dis, &A[n].price);
if(A[n].dis <= de) n++;
}
--n;
}
void solve()
{
init();
read_case();
int ans = dp();
if(ans != INF) printf("%d\n", ans);
else printf("Impossible\n");
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
solve();
if(T) printf("\n");
}
return 0;
}