UVa1025z城市里的间谍

题意:一个间谍要从第一个车站到第n个车站去会见另一个,在是期间有n个车站,有来回的两个轨道,发车方向相反,间谍身手敏捷,即使方向不同的两列车在同一时间到站,也能完成换乘。让你在时间T内时到达n,并且等车时间最短,输出最短等车时间。

思路:先用一个has_train[t][i][0]来表示在t时刻,在车站i,是否有往右开的车。同理,has_train[t][i][1]用来保存是否有往左开的车。
动态规划。
用d(i,j)表示时刻i,在车站j,最少还需要等待多长时间。边界条件是d(T,n)=0,其他d(T,i)为正无穷。

每次有三种决策:
①:等一分钟。
②:搭成往右开的车(如果有)。
③:搭成往左开的车(如果有)。

#include <cstdio>
#include <cstring>
#include <algorithm> 
using namespace std;
const int INF = 1<<30;
int start_T[55], dur[55], has_train[205][55][2], dp[205][55];
int main()
{
	int n,T; 
	int kase = 1;
	//freopen("in.txt","r",stdin);
	while(scanf("%d %d",&n,&T) == 2&&n){
		//输入,并计算has_train[i][j][0]:在i时刻,j站有向右的车(0表示右,1表示左) 
		memset(has_train,0,sizeof(has_train));
		for(int i = 1; i < n; ++i) scanf("%d",&dur[i]);
		int m1; scanf("%d",&m1);
		for(int i = 1; i <= m1; ++i) scanf("%d",&start_T[i]);
		
		for(int i = 1; i <= m1; ++i){
			int t = start_T[i];
			for(int j = 1; j <= n; ++j){
				if(t <= T) has_train[t][j][0] = 1;
				else break;
				t+= dur[j];
			}
		}
		
		scanf("%d",&m1);
		for(int i = 1; i <= m1; ++i) scanf("%d",&start_T[i]);
		for(int i = 1; i <= m1; ++i){
			int t = start_T[i];
			for(int j = n; j >= 1; --j){
				if(t <= T) has_train[t][j][1] = 1;
				else break;
				t+= dur[j-1];
			}
		}
		
		// 规划. dp[i][j] :i 时刻在 j 站还需等候多久 。要求的是dp[0][1] 
		for(int i = 0; i <= T; ++i )
			for(int j = 1; j <= n; ++j) dp[i][j] = 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+dur[j] <= T) //向右乘车
					dp[i][j] = min(dp[i][j], dp[i+dur[j]][j+1]);
				if(j > 1 && has_train[i][j][1] && i+dur[j-1] <= T) //向左乘车
					dp[i][j] = min(dp[i][j], dp[i+dur[j-1]][j-1]);
			}
		} 
		printf("Case Number %d: ", kase++);
		if(dp[0][1] >= INF ) printf("impossible\n");
		else printf("%d\n",dp[0][1]);
	}
}

猜你喜欢

转载自blog.csdn.net/CY05627/article/details/88292795
今日推荐