---恢复内容开始---
题意:有n(2<=n<=50)个车站,从左到右编号为1~n,有M1辆列车从第1站向右开,还有M2辆列车从第N站向左开。在时刻0,间谍从第1站出发,目的是在时刻T(0<=T<=200)会见在车站n的一个间谍。在车站等候容易被抓,所以需要尽量躲在火车上,使在车站等待的时间尽量的少,列车靠站时间忽略不计,即使2站方向相反列车在同一时间靠站,间谍也能完成换乘。
题解:由于时间有序,所以可以通过判断在时刻t,在车站i 最少需要等候多少时间进行DP。由于输入较2复杂,所以可以用has_train数组表示在时刻t,车站i是否有向左或者向右的火车。具体细节可见代码。
#include<cstdio> #include<iostream> #include<cstring> using namespace std; const int maxn = 50 + 5; const int maxt = 200 + 5; const int INF = 1000000000; int t[maxn],has_train[maxt][maxn][2],dp[maxt][maxn]; int main(){ int n,T,m1,m2,kase=0; while(~scanf("%d",&n)&&n){ scanf("%d",&T); for(int i=1;i<n;i++){ scanf("%d",&t[i]);///i到i+1的时间 } memset(has_train, 0, sizeof(has_train)); scanf("%d",&m1);int d; for(int i=0;i<m1;i++){ scanf("%d",&d); for(int j=1; j<n; j++) {///此处从1开始表示车站数 if(d<=T) has_train[d][j][0] = true;///d为时间,i为车站,表示在时间d时是否有向右的车可以搭乘 d+=t[j]; } } scanf("%d",&m2); for(int i=0;i<m2;i++){ scanf("%d",&d); for(int j=n-1;j>0;j--){ if(d<=T) has_train[d][j+1][1]=true;///d为时间,i为车站,表示在时间d时是否有向左的车可以搭乘 d+=t[j]; } } for(int i=1;i<n;i++) dp[T][i]=INF;///最终点不会在第n站之外 dp[T][n]=0; for(int i=T-1;i>=0;i--)///逆序倒推,对于每个车站都有3个选择,等待1个单位时间,搭乘向右的车,搭乘向左的车 for(int j=1;j<=n;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]);///对3种状态进行查询,找出最优解 } printf("Case Number %d: ",++kase); if(dp[0][1]>=INF) printf("impossible\n"); else printf("%d\n",dp[0][1]); } return 0; }
时间: 2024-10-11 10:59:24