题目链接:https://cn.vjudge.net/problem/UVA-1025
题目大意:Mario从第1站出发,目的是在时刻T会见车站
n
n
n 的一个间谍。由于在车站等待容易被抓,所以应尽量躲在开动的火车上,即在车站等待的时间最短,且Mario十分敏捷,及时两辆方向不同的列车在同一时间停靠,她也能完成换乘。
输入的第1行为
n
(
2
≤
n
≤
50
)
n(2 \le n \le 50)
n(2≤n≤50) ,第2行为
T
(
0
≤
T
≤
200
)
T(0 \le T \le 200)
T(0≤T≤200) ,第3行有
n
−
1
n-1
n−1 个整数
t
1
,
t
2
,
…
,
t
n
−
1
t_1,t_2,\dots,t_{n-1}
t1,t2,…,tn−1
(
1
≤
t
i
≤
70
)
(1 \le t_i \le 70)
(1≤ti≤70) ,其中
t
i
t_i
ti 表示地铁从车站
i
i
i 到车站
i
+
1
i+1
i+1 的行驶时间(两个方向一样)。第4行为
M
1
(
1
≤
M
1
≤
50
)
M1(1 \le M1 \le 50)
M1(1≤M1≤50),即从第1站出发向右开的列车数目。第5行包含
M
1
M1
M1 个整数
d
1
,
d
2
,
…
,
d
M
1
(
0
≤
d
i
≤
250
,
d
i
<
d
i
+
1
)
d_1,d_2,\dots,d_{M1}(0 \le d_i \le 250,d_i < d_{i+1} )
d1,d2,…,dM1(0≤di≤250,di<di+1) ,即各列车的出发时间。第6、7行描述从第
n
n
n 站出发向左开的列车,格式同第4、5行。输出仅包含1行,即最少等待时间。无解输出 impossible.
解题思路:用
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j] 来代表第
i
i
i 时刻在
j
j
j 车站的等待时间。在每一个车站,Mario有三种方法:1、等待1分钟
2、搭乘向左开的列车
3、搭乘向右开的列车
我们可以先假设终态为
d
p
[
T
]
[
n
]
=
0
dp[T][n]=0
dp[T][n]=0 ,然后再由终态往前推始态
d
p
[
0
]
[
1
]
dp[0][1]
dp[0][1] ,如果
d
p
[
0
]
[
1
]
≥
i
n
f
dp[0][1] \ge inf
dp[0][1]≥inf,则证明无法推到,输出impossible,否则输出
d
p
[
0
]
[
1
]
dp[0][1]
dp[0][1] 的值即可。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <set>
#include <utility>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define inf 0x3f3f3f3f
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define lep(i,l,r) for(int i=l;i>=r;i--)
#define ms(arr) memset(arr,0,sizeof(arr))
//priority_queue<int,vector<int> ,greater<int> >q;
const int maxn = (int)1e5 + 5;
const ll mod = 1e9+7;
int dp[1200][120];
int d1[1200][120],d2[1200][120];
int t[120];
int sum1[120],sum2[120];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
//freopen("out.txt", "w", stdout);
ios::sync_with_stdio(0),cin.tie(0);
int n,T,c=0;
while(scanf("%d",&n)!=EOF) {
if(n==0) break;
c++;
ms(sum1);ms(sum2);
ms(d1);ms(d2);
ms(t);
scanf("%d",&T);
rep(i,1,n-1) {
scanf("%d",&t[i]);
sum1[i]=sum1[i-1]+t[i];
}
lep(i,n-1,1) sum2[i]=sum2[i+1]+t[i];
int m1,m2;
scanf("%d",&m1);
int nape;
rep(i,1,m1) {
scanf("%d",&nape);
d1[nape][1]=1;
rep(j,1,n-1) {
d1[nape+sum1[j]][j+1]=1;
}
}
scanf("%d",&m2);
rep(i,1,m2) {
scanf("%d",&nape);
d2[nape][n]=1;
lep(j,n-1,1) {
d2[nape+sum2[j]][j]=1;
}
}
rep(i,1,n-1) 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&&d1[i][j]==1&&i+t[j]<=T)
dp[i][j]=min(dp[i][j],dp[i+t[j]][j+1]);
if(j>1&&d2[i][j]==1&&i+t[j-1]<=T)
dp[i][j]=min(dp[i][j],dp[i+t[j-1]][j-1]);
}
}
printf("Case Number %d: ",c);
if(dp[0][1]>=inf) printf("impossible\n");
else printf("%d\n",dp[0][1]);
}
return 0;
}