题面
某城市地铁是线性的,有n(2≤n≤50)个车站,从左到右编号1~n。有M1辆列车从第1站开始往右开,还有M2辆列车从第n站开始往左开。列车在相邻站台间所需的运行时间是固定的,因为所有列车的运行速度是相同的。在时刻0,Mario从第1站出发,目的在时刻T(0≤T≤200)会见车站n的一个间谍。在车站等车时容易被抓,所以她决定尽量躲在开动的火车上,让在车站等待的时间尽量短。列车靠站停车时间忽略不计,且Mario身手敏捷,即时两辆方向不同的列车在同一时间靠站,Mario也能完成换乘。 【输入格式】 输入文件包含数种情况,每一种情况包含以下7行:
第一行是一个正整数n,表示有n个车站 第二行是为T,表示Mario在时刻T见车站n的间谍 第三行有n-1个整数t1,t2,...,tn-1,其中ti表示地铁从车站i到i+1的行驶时间 第四行为M1,及从第一站出发向右开的列车数目 第五行包含M1个正整数a1,a2,...,aM1,即个列车出发的时间 第六行为M2,及从第一站出发向右开的列车数目 第七行包含M2个正整数b1,b2,...,bM2,即个列车出发的时间
最后一种情况以一行0结尾。
思路
先用一个map[t][i][0]来表示在t时刻,在车站i,是否有往右开的车。同理,map[t][i][1]用来保存是否有往左开的车。
用d(i,j)表示时刻i,你在车站j,最少还需要等待多长时间。边界条件是d(t,n)=0,其他d(t,i)为正无穷。
每次有三种决策:
①:等一分钟
②:搭成往右开的车(如果有)
③:搭成往左开的车(如果有) ——摘自紫书
代码
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int t,f[1003][103],n,tt[102],star,m,kase;
bool map[1003][103][2];
int main()
{
while(cin>>n&&n!=0)
{
memset(map,0,sizeof(map));
memset(f,0,sizeof(f));
memset(tt,0,sizeof(tt));
cin>>t;
for(register int i=1;i<n;i++)cin>>tt[i];
cin>>m;
for(register int i=1;i<=m;i++){
cin>>star;
for(register int l=1;l<=n&&star<=t;l++)
map[star][l][0]=1,star+=tt[l];
}//预处理×1
cin>>m;
for(register int i=1;i<=m;i++){
cin>>star;
for(register int l=n;l>1&&star<=t;l--)
map[star][l][1]=1,star+=tt[l-1];
}//预处理×2
for(register int i=1;i<n;i++)f[t][i]=0x3f3f3f3;//预处理×3
for(register int i=t-1;i>=0;i--)//注意这里是从后往前倒序枚举
for(register int l=1;l<=n;l++){
f[i][l]=f[i+1][l]+1;
if(map[i][l][0]&&l<n&&i+tt[l]<=t)
f[i][l]=min(f[i][l],f[i+tt[l]][l+1]);//考虑向乘车向右走
if(map[i][l][1]&&l>1&&i+tt[l-1]<=t)
f[i][l]=min(f[i][l],f[i+tt[l-1]][l-1]);//考虑乘车向左走
}
cout<< "Case Number " <<++kase<< ": ";
if(f[0][1]>=0x3f3f3f3) cout<< "impossible\n";
else cout<<f[0][1]<<"\n";
}
return 0;
}
总结
这道题主要需要理解为什么倒序枚举
预处理注意细节
多组数据故每次都要初始化一下