题意:某城市的地铁是线性的,有n(2<=n<=50)个车站,从左到右的编号为1~n。有M1辆车从第1站出发往右开,还有M2辆车从第n站开始往左开。
在时刻0,Mario从第1站出发,目的是在时刻T(0<=T<=200)会见车站n的一个间谍。在车站等车时容易被抓,所以她决定躲在开动的火车上,让在
车站等待的总时间尽量短。列车靠站停车时间忽略不计,且Mario身手敏捷,即使两辆方向不同的列车在同一时间靠站,Mario也能完成换乘。
题解:时间是单向流逝的,是一个天然的序。影响到决策的只有当前时间和所处的车站,所以可以用d(i,j)表示时刻 i ,你在车站 j ,最少还需要等
待多长时间。边界条件d(T,n)=0,其他d(T,j)(j 不等于n)为正无穷。有如下三种决策:
(1)等一分钟。
(2)搭乘往右开的车(如果有)
(3)搭乘往左开的车(如果有)
NOTE:以上摘自《算法竞赛入门经典》
读完这个题的时候大脑一片混乱,不知从那下手,更不用说如何定义状态。个人总结,有时DP得逆着推,比如数字三角形,单向TSP等等。这道题也
是,还有就是注意控制边界条件啊,初始化啊。路漫漫其修远兮!
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define INF 1e8 6 using namespace std; 7 8 int n,T,kase; 9 int dp[205][55],t[55]; 10 bool train[205][55][2]; 11 12 void read(){ 13 cin>>T; 14 for(int i=1;i<n;i++) cin>>t[i]; 15 16 int x;cin>>x; 17 for(int i=0;i<x;i++){ 18 int y;cin>>y; 19 train[y][1][0]=true; 20 int sum=0; 21 for(int j=1;j<n;j++){ 22 sum=sum+t[j]; 23 if(y+sum<=T) train[y+sum][j+1][0]=true; 24 } 25 } 26 27 cin>>x; 28 for(int i=0;i<x;i++){ 29 int y;cin>>y; 30 train[y][n][1]=true; 31 int sum=0; 32 for(int j=n-1;j>0;j--){ 33 sum=sum+t[j]; 34 if(y+sum<=T) train[y+sum][j][1]=true; 35 } 36 } 37 } 38 39 void solve(){ 40 for(int i=1;i<n;i++) dp[T][i]=INF; 41 dp[T][n]=0; 42 for(int i=T-1;i>=0;i--){ 43 for(int j=1;j<=n;j++){ 44 dp[i][j]=dp[i+1][j]+1; 45 if(j<n&&train[i][j][0]&&i+t[j]<=T) dp[i][j]=min(dp[i][j],dp[i+t[j]][j+1]); 46 if(j>1&&train[i][j][1]&&i+t[j-1]<=T) dp[i][j]=min(dp[i][j],dp[i+t[j-1]][j-1]); 47 } 48 } 49 50 cout<<"Case Number "<<++kase<<": "; 51 if(dp[0][1]>=INF) cout<<"impossible\n"; 52 else cout<<dp[0][1]<<"\n"; 53 } 54 int main() 55 { kase=0; 56 while(cin>>n&&n){ 57 memset(train,false,sizeof(train)); 58 read(); 59 solve(); 60 } 61 return 0; 62 }
时间: 2024-11-09 22:34:55