UVA1025 A Spy in the Metro —— DP
题目链接: https://vjudge.net/problem/UVA-1025
题解:
详情请看紫书P267。 与其说是DP题,我觉得更像是模拟题,特别是用记忆化搜索写。
递推:
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <string> #include <vector> #include <map> #include <set> #include <queue> #include <sstream> #include <algorithm> using namespace std; #define pb push_back #define mp make_pair #define ms(a, b) memset((a), (b), sizeof(a)) #define eps 0.0000001 typedef long long LL; const int INF = 2e9; const LL LNF = 9e18; const int mod = 1e9+7; const int maxn = 200+10; int n, T, M1, M2; int t[maxn], has_train[maxn][maxn][2], dp[maxn][maxn]; int kase = 0; void init() { ms(t,0); ms(has_train,0); ms(dp,0); scanf("%d",&T); for(int i = 1; i<n; i++) scanf("%d",&t[i]); int M1, x; scanf("%d",&M1); for(int i = 1; i<=M1; i++) { scanf("%d",&x); for(int j = 1; j<=n && x<=T; j++) { has_train[x][j][0] = 1; x += t[j]; } } int M2; scanf("%d",&M2); for(int i = 1; i<=M2; i++) { scanf("%d",&x); for(int j = n; j>=1 && x<=T; j--) { has_train[x][j][1] = 1; x += t[j-1]; } } } void solve() { for(int i = 1; i<=n-1; i++) dp[i][j] = INF; dp[T][n] = 0; for(int i = T-1; i>=0; i--) for(int j = n; j>=1; j--) { dp[i][j] = dp[i+1][j] + 1; if(j<n && has_train[i][j][0] && i+t[j]<=T) dp[i][j] = min(dp[i][j], dp[i+t[j]][j+1]); if(j>1 && has_train[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: ",++kase); if(dp[0][1]<INF) printf("%d\n",dp[0][1]); else puts("impossible"); } int main() { while(scanf("%d",&n) && n) { init(); solve(); } return 0; }
记忆化搜索:
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <string> #include <vector> #include <map> #include <set> #include <queue> #include <sstream> #include <algorithm> using namespace std; #define pb push_back #define mp make_pair #define ms(a, b) memset((a), (b), sizeof(a)) #define eps 0.0000001 typedef long long LL; const int INF = 2e9; const LL LNF = 9e18; const int mod = 1e9+7; const int maxn = 200+10; int n, T, M1, M2; int t[maxn], has_train[maxn][maxn][2], dp[maxn][maxn]; int kase = 0; void init() { ms(t,0); ms(has_train,0); ms(dp,-1); scanf("%d",&T); for(int i = 1; i<n; i++) scanf("%d",&t[i]); int M1, x; scanf("%d",&M1); for(int i = 1; i<=M1; i++) { scanf("%d",&x); for(int j = 1; j<=n && x<=T; j++) { has_train[x][j][0] = 1; x += t[j]; } } int M2; scanf("%d",&M2); for(int i = 1; i<=M2; i++) { scanf("%d",&x); for(int j = n; j>=1 && x<=T; j--) { has_train[x][j][1] = 1; x += t[j-1]; } } for(int i = 1; i<n; i++) dp[T][i] = INF; dp[T][n] = 0; } int dfs(int i, int j) { if(dp[i][j]!=-1) return dp[i][j]; dp[i][j] = dfs(i+1, j) + 1; if(j<n && has_train[i][j][0] && i+t[j]<=T) dp[i][j] = min( dp[i][j], dfs( i+t[j], j+1 ) ); if(j>1 && has_train[i][j][1] && i+t[j-1]<=T) dp[i][j] = min( dp[i][j], dfs( i+t[j-1], j-1 ) ); return dp[i][j]; } int main() { while(scanf("%d",&n) && n) { init(); dfs(0,1); printf("Case Number %d: ",++kase); if(dp[0][1]<INF) printf("%d\n",dp[0][1]); else puts("impossible"); } return 0; }