UVA1025 城市里的间谍 A Spy in the Metro

 实际上这题就是问Mario最少的总等车时间

这题我的做法是

把一个火车从左到右(或从右到左) 的过程

转化成

途中任何车站到左边(或右边)相邻车站 的过程

相当于把他切成了一段一段

(一段就是两个相邻车站中间的部分)

这样更容易操作

具体请看代码

一些注释代码里请往下看

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int Time = 205, N = 55;

bool has_train[20 * N][N][2];
int dp[Time][N], t[N];

int main() {
	int n, T, Case;
	Case = 0;
	while (scanf ("%d", &n), n) {
		memset(t, 0, sizeof t);
		memset(has_train, false, sizeof has_train);
		scanf ("%d", &T);
		int tmp = 0;
        //t[i] : 从第i个车站 ~ 第i+1个车站 耗费的时间 (反向也是)
		for (int i = 1; i < n; i ++)
			scanf ("%d", &t[i]);
		int ml, mr;
        //ml 是从第一站向右开的火车的发班时间
		scanf ("%d", &ml);
        //下面两个while是用来编写has_train的  具体has_train的意义下面会讲
		while (ml --) {
			int di;
			scanf ("%d", &di); //发班时间
			int time = di;
			for (int k = 1; k <= n; k ++)
				has_train[time += t[k - 1]][k][0] = true; //向右
		}
        //mr 是从最后一站向左开的火车的发班时间
		scanf ("%d", &mr);
		while (mr --) {
			int di;
			scanf ("%d", &di); //发班时间
			int time = di;
			for (int k = n; k >= 1; k --)
				has_train[time += t[k]][k][1] = true; //向左
		}

		/*
		dp(i,j) 第i个时刻在第j个车站 最少等的总时间

		三种情况:
			1). 等一分钟
				dp(i,j) = dp(i+1,j) + 1;
			2). 坐往右开的车(如果有)
				dp(i,j) = dp(i+t[j],j+1)
			3).	坐往左开的车(如果有)
				dp(i,j) = dp(i+t[j-1],j-1)
			三个状态去一个min

		所有初始化成一个0x7f7f7f7f (及无解)
		dp(T,n)=0;

        has[i][j][sign] : 第i个时刻第j个车站是否有向右(sign == 0)或左(sign == 1)的车
		*/
		for (int i = 1; i < n; i ++)
			dp[T][i] = 0x7f7f7f7f;
		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]);
			}
		}

		int ans = dp[0][1];
		printf ("Case Number %d: ", ++ Case);
		if (ans < 0x7f7f7f7f)
			printf ("%d\n", ans);
		else
			printf ("impossible\n");
	}
	return 0;
}

题目传送门:UVA1025 城市里的间谍

制作不易,留个赞再走吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值