A Spy in the Metro UVA-1025(dp)
- 分析
我的第一个动归题哈哈,一开始甚至写成了 dfs 。动归题其实都可以用 dfs ,但是太多的重复计算会导致超时。这个题其实可以以时间为主线,通过两层循环填表来解决。紫书上是逆推的,其实顺推和逆推都可以,逆推更方便。
刚开始以为 “Trainsmove in both directions: from the first station to the last station and from the last station back to the first station.” 是说车到达终点站后会折返,事实上只是说两个方向的车行驶方向不同而已。车到达终点站后不会折返。
- AC 代码
顺推:
/*
*lang C++ 5.3.0
*user Weilin_C
*/
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int main()
{
int N, T, station[50], c = 0;
int rightT[205][25], leftT[205][25], tr, tl;
int dp[500][50];
while (scanf("%d", &N) && N) {
int t;
memset(rightT, 0, sizeof(rightT));
memset(leftT, 0, sizeof(leftT));
scanf("%d", &T);
for (int i = 0; i < N-1; i++)
scanf("%d", &station[i]);
scanf("%d", &tr);
for (int i = 0; i < tr; i++) {
scanf("%d", &t);
for (int ti = t, st = 0; ti <= T && st < N; st++) {
rightT[ti][st] = 1;
ti += station[st];
}
}
scanf("%d", &tl);
for (int i = 0; i < tl; i++) {
scanf("%d", &t);
for (int ti = t, st = N-1; ti <= T && st > 0; st--) {
leftT[ti][st] = 1;
ti += station[st-1];
}
}
//初始化为比 T 大就行,也可以用 memset(dp, 1, sizeof(dp));
for (int i = 0; i <= T; i++)
for (int j = 0; j <= N; j++)
dp[i][j] = T+1;
dp[0][0] = 0;
for (int i = 1; i <= T; i++) {
for (int j = 0; j < N; j++) {
dp[i][j] = dp[i-1][j] + 1;
if (j > 0 && i >= station[j-1] && rightT[i-station[j-1]][j-1]) { //有右向车到达
dp[i][j] = min(dp[i][j], dp[i-station[j-1]][j-1]);
}
if (j < N-1 && i >= station[j] && leftT[i-station[j]][j+1]) { //有左向车到达
dp[i][j] = min(dp[i][j], dp[i-station[j]][j+1]);
}
}
}
printf("Case Number %d: ", ++c);
if (dp[T][N-1] > T) printf("impossible\n");
else printf("%d\n", dp[T][N-1]);
}
return 0;
}
逆推和紫书上差不多:
dp[T][N-1] = 0;
for (int i = T-1; i >= 0; i--) {
for (int j = 0; j < N; j++) {
dp[i][j] = dp[i+1][j] + 1;
if (j < N-1 && i + station[j] <= T && rightT[i][j]) { //有右向车出发
dp[i][j] = min(dp[i][j], dp[i + station[j]][j+1]);
}
if (j > 0 && i + station[j-1] <= T && leftT[i][j]) { //有左向车出发
dp[i][j] = min(dp[i][j], dp[i + station[j-1]][j-1]);
}
}
}
printf("Case Number %d: ", ++c);
if (dp[0][0] > T) printf("impossible\n");
else printf("%d\n", dp[0][0]);
by SDUST weilinfox
原文链接:https://www.cnblogs.com/weilinfox/p/12559058.html