题目链接: 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;
}