例题9-1 城市里的间谍 UVa1025

1.题目描述:点击打开链接

2.解题思路:本题利用动态规划解决,时刻i和所在的车站j构成了一个状态,每个状态都有三种决策:(1)等待1分钟。(2)搭乘向右开的车(如果有)。(3)搭乘向左开的车(如果有)。如果用d(i,j)表示在时刻i,位于车站j时最少的等待时间,那么对于三种决策,可得到如下的状态转移方程:

(1) d(i,j)=d(i+1,j)+1;

(2) d(i,j)=min(d(i,j),d(i+t[j],j+1));

(3) d(i,j)=min(d(i,j),d(i+t[j-1],j-1));

处理状态之前可以先用数组has_train表示时刻i,位于车站j,有无向右(向左)的车。

3.代码:

#define _CRT_SECURE_NO_WARNINGS 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

#define INF 9999999
#define maxn 250+50
int T, n, m1, m2;
int t[maxn];
int a[maxn], b[maxn];
int has_train[maxn][maxn][2];
int dp[maxn][maxn];
int main()
{
	//freopen("test.txt", "r", stdin);
	int kase = 0;
	while (scanf("%d", &n) == 1 && n)
	{
		memset(has_train, 0, sizeof(has_train));
		scanf("%d", &T);
		t[0] = 0;
		t[n] = 0;
		for (int i = 1; i <= n - 1; i++)
			scanf("%d", t + i);
		scanf("%d", &m1);
		for (int i = 1; i <= m1; i++)
		{
			scanf("%d", a + i);
			int sum = a[i];
			for (int j = 0; j <= n - 1; j++)
			{
				sum += t[j];
				has_train[sum][j + 1][0] = 1;
			}
		}
		scanf("%d", &m2);
		for (int i = 1; i <= m2; i++)
		{
			scanf("%d", b + i);
			int sum = b[i];
			for (int j = n; j >= 1; j--)
			{
				sum += t[j];
				has_train[sum][j][1] = 1;
			}
		}
		for (int i = 1; i <= n - 1; i++)
			dp[T][i] = INF;
		dp[T][n] = 0;
		for (int i = T - 1; i >= 0;i--)
		for (int j = 1; j <= n; j++)
		{
			dp[i][j] = dp[i + 1][j] + 1;
			if (j < n&&has_train[i][j][0] && i + t[j] <= T)
				dp[i][j] = min(dp[i][j], dp[i + t[j]][j + 1]);
			if (j>1 && has_train[i][j][1] && i + t[j - 1] <= T)
				dp[i][j] = min(dp[i][j], dp[i + t[j - 1]][j - 1]);
		}
		cout << "Case Number " << ++kase << ": ";
		if (dp[0][1] >= INF)cout << "impossible\n";
		else cout << dp[0][1] << '\n';
	}
	return 0;
}

你可能感兴趣的:(算法竞赛入门经典(第二版))