题目链接:10201 - Adventures in Moving - Part IV
题目大意:有n个测试数据组, 对于每个测试组,最先给出一个距离lenth, 然后给出若干个加油站的位置以及加油站每升油的价钱。然后有量油桶容量为200升的卡车,出距离为0的位置开始移动向lenth,每升油可以使的卡车走一个单位距离,问,卡车到达lenth的时候,并且油箱中仍有100升油,最少花费多少钱,如果不能到达,输出“Impossible”。
解题思路:这题搁个有两三天了,一直没想清楚怎么写,后来仔细想了一下,可以用递推的方法,对每个加油站进行处理,dp[i][j],i代表第i个加油站,j表示油箱有多少升油。j的范围为0~200。然后除了起点之外,其他的油箱最大值为200,如果s[i].dis - s[i - 1].dis > top, 说明在中间的路程会出现断油,到达不了终点,并且dp[i][j]的最小值有两种来源,一种是从前一个加油站剩余的油,另一种是在本站加油。
#include <stdio.h> #include <string.h> const int N = 105; const int M = 205; const int MAX = 1 << 30; int min(int a, int b) { return a > b ? b : a; } struct star { int dis; int val; }s[N]; int n, ans, lenth, dp[N][M]; char str[N]; void read() { n = 1; memset(s, 0, sizeof(s)); int a, b; gets(str); sscanf(str, "%d", &lenth); while (gets(str) != NULL) { if(str[0] == '\0') break; sscanf(str, "%d%d", &a, &b); if (a > lenth) continue; s[n].dis = a; s[n].val = b; n++; } } bool solve() { memset(dp, -1, sizeof(dp)); int top = 100, l; s[0].dis = 0; for (int i = 0; i <= 100; i++) dp[0][i] = 0; for (int i = 101; i <= 200; i++) dp[0][i] = MAX; for (int i = 1; i < n; i++) { l = s[i].dis - s[i - 1].dis; if (l > top) return false; else dp[i][0] = dp[i - 1][l]; for (int j = 1; j <= 200; j++) { dp[i][j] = dp[i][j - 1] + s[i].val; if (l + j > top) continue; dp[i][j] = min(dp[i][j], dp[i - 1][l + j]); } top = 200; } l = lenth - s[n - 1].dis; if (l > top) return false; else dp[n][0] = dp[n - 1][l]; for (int i = 1; i <= 100; i++) { if (i + l > top) return false; dp[n][i] = dp[n - 1][i + l]; } ans = dp[n][100]; return true; } int main(){ int cas; gets(str); sscanf(str, "%d", &cas); gets(str); while (cas--) { read(); if (solve()) printf("%d\n", ans); else printf("Impossible\n"); if (cas) printf("\n"); } return 0; }