Uva 1025 A Spy in the Metro
用dp[i][j]表示i时刻在车站j还需要等待的最小时间。很容易得到边界条件dp[T][n]=0,dp[T][1...n-1]=INF;我们要求的便是dp[0][1].考虑每次的三个决策:
1)等待1分钟
2)搭乘向右的车(如果有)
3)搭乘向左的车(如果有)
dp[i][j]=max(dp[i+1][j],dp[i+t[i]][j+1],dp[i+t[j-1]][j-1]); //此处是倒着推的
/*---dp[i][j]表示i时刻在j站还需要等待的时间
----边界条件dp[T][n]=0,dp[T][1...n-1]=INF;
得到dp[i][j]有如下三种决策:
1)时刻在j站等待一分钟
2)搭乘向右的车(如果有)
3)搭乘向左的车(如果有)
---初始化has[i][j][0]表示i时刻在j站是否有向右的车
---初始化has[i][j][1]表示i时刻在j站是否有向左的车
*/
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<vector>
#include<string.h>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long LL;
const int MAXN = 50 + 10;
int a[MAXN];
int b[MAXN];
int has[200 + 10][MAXN][2];
int t[MAXN];
int dp[200 + 10][MAXN];
int n, m1, m2,T;
bool vis[200 + 10][MAXN];
//记忆化搜索
int dfs(int i, int j){
int &ans = dp[i][j];
if (vis[i][j])
return ans;
vis[i][j] = 1;
ans = dfs(i + 1, j) + 1; //等待一分钟
if (j<n&&(i + t[j])<= T&&has[i][j][0])
ans = min(ans, dfs(i + t[j], j + 1));
if (j>1 && i + t[j - 1] <= T&&has[i][j][1])
ans = min(ans, dfs(i + t[j - 1], j - 1));
return ans;
}
int main(){
int i, j,iCase=1;
while (scanf("%d", &n) && n){
scanf("%d", &T);
for (i = 1; i < n; i++)
scanf("%d", &t[i]);
t[n] = t[0] = 0;
scanf("%d", &m1);
for (i = 1; i <=m1; i++)
scanf("%d", &a[i]);
scanf("%d", &m2);
for (i = 1; i <= m2; i++)
scanf("%d", &b[i]);
memset(has, 0, sizeof(has));
for (i = 1; i <= m1; i++){
int p = a[i];
for (j = 1; j <= n; j++){
p += t[j - 1];
if (p > T)
break;
has[p][j][0] = 1;
}
}
for (i = 1; i <= m2; i++){
int p = b[i];
for (j =n; j>0; j--){
p += t[j];
if (p > T)
break;
has[p][j][1] = 1;
}
}
memset(dp[T], 0x3f, sizeof(dp[T]));
dp[T][n] = 0;
memset(vis, 0, sizeof(vis));
for (i = 1; i <=n; i++)
vis[T][i] = 1;
dp[0][1] = dfs(0, 1);
printf("Case Number %d: ", iCase++);
if (dp[0][1] >= INF)
printf("impossible\n");
else
printf("%d\n", dp[0][1]);
}
return 0;
}

浙公网安备 33010602011771号