紫书DP第一道例题,实力不够,刷不动exercises,只能来刷examples。首先找出“状态”,根据状态来DP。dp[i][j],i表示当前时间,j表示车站号,数组存还需要等待的最短时间。然后分析决策种类,共有三种,等待一分钟,搭乘正方向的车,搭乘反方向的车,逆向DP,在三种决策中选出最优。DP前预处理好在某个时间某个车站是否有车。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <ctype.h>
#define INF 1000000
using namespace std;
int t[60];//相邻两站时间
int d[60];//M1
int e[60];//M2
bool dd[350][60];
bool ee[350][60];
int dp[350][60];
int main(){
int N;//车站数 max 50
int T;//约定时间 max200
int M1;//从第一个站发的车
int M2;//从最后一个站发的车
int _case=0;
while(cin>>N){
if(!N)break;
cin>>T;
t[0]=t[N]=0;
for(int i=1;i<N;i++)cin>>t[i];
cin>>M1;
for(int i=1;i<=M1;i++)cin>>d[i];
cin>>M2;
for(int i=1;i<=M2;i++)cin>>e[i];
//init
for(int i=0;i<350;i++){
for(int j=0;j<60;j++)dp[i][j]=INF;
}
dp[T][N]=0;
memset(dd,0,sizeof(dd));memset(ee,0,sizeof(ee));
for(int i=1;i<=M1;i++){
int tmp=0;
for(int j=1;j<N;j++){
tmp+=t[j-1];
dd[d[i]+tmp][j]=true;
}
}
for(int i=1;i<=M2;i++){
int tmp=0;
for(int j=N;j>1;j--){
tmp+=t[j];
ee[e[i]+tmp][j]=true;
}
}
for(int i=T-1;i>=0;i--){
for(int j=N;j>=1;j--){
int tmp=INF;
//向右开
if(j<N&&dd[i][j]&&dp[i+t[j]][j+1]!=INF){
tmp=min(tmp,dp[i+t[j]][j+1]);
}
//向左
if(j>1&&ee[i][j]&&dp[i+t[j-1]][j-1]!=INF){
tmp=min(tmp,dp[i+t[j-1]][j-1]);
}
//等
if(dp[i+1][j]!=INF)tmp=min(tmp,dp[i+1][j]+1);
dp[i][j]=tmp;
}
}
_case++;
cout<<"Case Number "<<_case<<": ";
if(dp[0][1]!=INF){
cout<<dp[0][1]<<endl;
}else{
cout<<"impossible"<<endl;
}
}
return 0;
}
本文介绍了一种基于动态规划的公交调度算法实现,通过分析不同情况下的最优选择(等待、正向乘车或反向乘车),解决从起点到终点的最短等待时间问题。文章详细解释了状态转移方程,并提供了完整的C++代码实现。
266

被折叠的 条评论
为什么被折叠?



