这个题目其实还是很简单的,属于入门级别的动态规划
这道题的特点有如下几点:
第一:起点固定,终点固定
第二:在理解题意的时候,应该要理解到,如果有解,那么在T时刻,这货一定是在第n个station的。如果没有解,那么一定是第一趟从起点出发的列车在T之前走不到终点。
第三:虽然在列车上时,这货所在的位置也是能够确定的,但是这样就会带来很多的麻烦,不如直接忽略掉这部分。
下面是我使用记忆化搜索来写的dp解答:汝佳使用递推写的。
//状态是某个时刻在某个位置 //d(i,j)表示还需要在这个状态等多久, //转移方程是, //如果选择等一分钟,那么d(i,j) = d(i + 1,j) + 1 //如果此时有向右的火车(而且坐上这趟火车直到它停车的时候,不会超过T),那么d(i,j) = d(i + x,j + 1) + x; //如果此时有向左的火车,那么d(i,j) = d(i + y,j - 1) + y; //取这三者的最小值 //当然一开始得先设置d(T,k) = MAX; d(T,n) = 0; //最后的结果如果可以正好到达,那不错 //如果不可以 //我刚才卡在了把 没有准时到达N点误解为了无解 //总的来说就是,找到所有可能的状态点,和在每一个状态点可行的决策(转移)方式,以及找到终点状态 //不管要等多久,都需要在最后的时刻处于最后一个station #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAX = 10000; const int maxt = 300; const int maxn = 55; int have_train_right[maxt][maxn]; int have_train_left[maxt][maxn]; int gap[maxn]; int d[maxt][maxn]; int num_station; int time; //如果无解,绝对是从起点出发的列车太迟了,导致人停在了某一个地方无法移动,由于是求t1 t2 t3的最小值,所以一定是MAX int dp(int t,int n)//计算t时刻,第n个station的需要等待的时间 { if(d[t][n] != -1) return d[t][n]; //三种决策,计算最小的值 int t1 = MAX,t2 = MAX,t3 = MAX; if(have_train_right[t][n] && t + gap[n] <= time) { t1 = dp(t + gap[n],n + 1); } if(have_train_left[t][n] && t + gap[n - 1] <= time) { t2 = dp(t + gap[n - 1],n - 1); } t3 = dp(t + 1,n) + 1; if(min(t1,t2) < t3) { d[t][n] = min(t1,t2); } else d[t][n] = t3; return d[t][n]; } bool read_input() { memset(d,-1,sizeof(d)); memset(have_train_right,0,sizeof(have_train_right)); memset(have_train_left,0,sizeof(have_train_left)); memset(gap,0,sizeof(gap)); scanf("%d%d",&num_station,&time); if(!num_station) return false; for(int i = 0;i < num_station - 1;i++) { scanf("%d",&gap[i]); } int M; scanf("%d",&M); for(int i = 0;i < M;i++) { int t; scanf("%d",&t); for(int j = 0;j < num_station - 1;j++) { have_train_right[t][j] = 1; t = t + gap[j]; if(t > time) break; } } scanf("%d",&M); for(int i = 0;i < M;i++) { int t; scanf("%d",&t); for(int j = num_station - 1;j > 0;j--) { have_train_left[t][j] = 1; t = t + gap[j - 1]; if(t > time) break; } } for(int i = 0;i < num_station - 1;i++) { d[time][i] = MAX; } d[time][num_station - 1] = 0; return true; } int main() { #ifdef local freopen("input.txt","r",stdin); freopen("out.txt","w",stdout); #endif int kase = 0; while(read_input()) { printf("Case Number %d: ",++kase); int x = dp(0,0); if(x >= MAX) { printf("impossible\n"); } else printf("%d\n",x); } return 0; }