uva 10201 - Adventures in Moving - Part IV(dp)

题目链接: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;
}


你可能感兴趣的:(uva 10201 - Adventures in Moving - Part IV(dp))