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; }