版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Q1410136042/article/details/80428370
题目链接:UVA-1025
题意:
给定n个车站,时间T,列车从车站i到车站i+1需要的时间t[i]。给定M1辆从车站1驶往车站n的列车发车时间,以及M2辆从车站n驶往车站1的列车发车时间。皮皮怪初始在车站1,要在T时刻到达车站n,问他至少要在车站等多久——车在车站停留时间忽略不计,并且假设皮皮怪特别敏捷,两辆车同时到车站他也能完成换乘,如果T时刻不可能在车站n就输出impossible。
分析:
这是一个很明显的多决策的问题,假设皮皮 i 时刻在车站 j(以dp[i][j]表示从现在开始他需要在车站等车的最少时间),那么他有三个决策:
(1)原地等一秒:dp[i][j] = dp[i+1][j]
(2)如果有向左的列车可搭乘:dp[i][j] = dp[i+t[i-1]][j-1]
(3)如果有向右的列车可搭乘:dp[i][j] = dp[i+t[i]][j+1]
我们需要做的就是在三个决策寻找最优的,也就是三个里最小的~
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<map>
#include<vector>
#include<iomanip>
#include<algorithm>
#include<string>
#include<cstring>
#define LL long long
#define DEBUG printf("DEBUG\n")
#define FOR(i, s, n) for(int i = s; i < n; ++ i)
#define For(i, s, n) for(int i = s; i > n; -- i)
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
const int maxn = 1e5;
using namespace std;
int main()
{
#ifdef AFei
freopen("in.c", "r", stdin);
#endif // AFei
int n, T, _case = 1;
int t[55];
// n, T, t都是题目里的意思, _case是统计第几个case的
bool hasTrain[210][55][2];
// hasTrain[i][j][k]表示i时刻,j车站是否有火车,k为1表示向右,为0表示向左
int dp[210][55];
// dp[i][j]表示i时刻在j车站的情况下,还需要等待的时间
while(scanf("%d", &n), n)
{
scanf("%d", &T);
memset(hasTrain, 0, sizeof hasTrain);
memset(dp, 0x3f, sizeof dp);
dp[T][n] = 0;
FOR(i, 1, n) scanf("%d", &t[i]);
int M, x;
scanf("%d", &M);
FOR(i, 0, M)
{
scanf("%d", &x);
if(x <= T)
{
hasTrain[x][1][1] = 1;
FOR(j, 1, n-1)
{
x += t[j];
if(x > T)
break;
hasTrain[x][j+1][1] = 1;
//处理向右的车到每一个车站的时间,不考虑最后一个车站
}
}
}
scanf("%d", &M);
FOR(i, 0, M)
{
scanf("%d", &x);
if(x <= T)
{
hasTrain[x][n][0] = 1;
For(j, n, 2)
{
x += t[j-1];
if(x > T)
break;
hasTrain[x][j-1][0] = 1;
//处理向左的车到每一个车站的时间,不考虑第一个车站
}
}
}
For(i, T-1, -1)
{
For(j, n, 0)
{
int& tmp = dp[i][j];
tmp = min(tmp, dp[i+1][j]) + 1;
if(hasTrain[i][j][1] && i+t[j] <= T)//如果有向右的车
tmp = min(tmp, dp[i+t[j]][j+1]);
if(hasTrain[i][j][0] && i+t[j-1] <= T)//如果有向左的车
tmp = min(tmp, dp[i+t[j-1]][j-1]);
}
}
if(dp[0][1] > T)
printf("Case Number %d: impossible\n", _case ++);
else
printf("Case Number %d: %d\n", _case ++, dp[0][1]);
}
return 0;
}