(http://www.elijahqi.win/2018/01/07/bzoj2538-ctsc2000%E5%85%AC%E8%B7%AF%E5%B7%A1%E9%80%BB/)
题目描述
在一条没有分岔的高速公路上有n个关口,相邻两个关口之间的距离都是10km。所有车辆在这条高速公路上的最低速度为60km/h,最高速度为120km/h,并且只能在关口处改变速度。巡逻的方式是在某个时刻Ti从第ni个关口派出一辆巡逻车匀速驶抵第(ni+1)个关口,路上耗费的时间为ti秒。
两辆车相遇是指它们之间发生超车或者两车同时到达某关口(同时出发不算相遇)。
巡逻部门想知道一辆于6点整从第1个关口出发去第n个关口的车(称为目标车)最少会与多少辆巡逻车相遇,请编程计算之。假设所有车辆到达关口的时刻都是整秒。
输入输出格式
输入第一行为两个用空格隔开的整数,分别为关口数n和巡逻车数m。
输出格式:
输出第一行为目标车与巡逻车相遇次数。第二行为目标车与巡逻车相遇次数最少时最早到达第n个关口的时刻(格式同输入中的Ti)。
输入输出样例
输入样例#1: 复制
3 2
1 060000 301
2 060300 600
输出样例#1: 复制
0
061301
说明
每个测试点1s
ctsc2000t第一试
洛谷一直不开o2跑不过 于是加了点小的剪枝就okay了
设f[i][j]表示到达第i号位置花费时间为j 遇到的最少的巡逻车的数量是多少
那么我如果从前面转移过来的话 因为有这个60km/h和120km/h的限速 所以最多是300s~600s这个区间内 所以我每次只需要去枚举一下我是由前面区间中哪个转移过来即可 剪枝就是 如果已经为0了 那么直接退出就好
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 330
#define inf 0x3f3f3f3f
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0;char ch=gc();
while(ch<'0'||ch>'9') ch=gc();
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=gc();}return x;
}
int st[55][N],ed[55][N],n,m,dp[55][40000],cnt[55];
inline int change(int x){return (x/10000-6)*3600+(x/100-x/10000*100)*60+x%100;}
inline int calc(int pos,int st1,int ed1){
int tmp=0;
for (int i=1;i<=cnt[pos];++i){
if(ed[pos][i]==ed1) {tmp++;continue;}
if (st1>st[pos][i]&&ed1<ed[pos][i]) {tmp++;continue;}
if (st1<st[pos][i]&&ed1>ed[pos][i]) {tmp++;continue;}
}return tmp;
}
int main(){
// freopen("1499.in","r",stdin);
n=read();m=read();
for (int i=1;i<=m;++i){
int start=read(),time=read(),time_last=read();
st[start][++cnt[start]]=change(time);ed[start][cnt[start]]=st[start][cnt[start]]+time_last;
}memset(dp,0x3f,sizeof(dp));dp[1][0]=0;
for (int i=2;i<=n;++i){
int l=(i-1)*300,r=(i-1)*600;
for (int j=l;j<=r;++j){
for (int k=300;k<=600;++k){
dp[i][j]=min(dp[i][j],dp[i-1][j-k]+calc(i-1,j-k,j));
if (!dp[i][j]) break;
}
}
}int l=(n-1)*300,r=(n-1)*600,ans=inf,time=0;
for (int i=l;i<=r;++i) {
if (dp[n][i]<ans) ans=dp[n][i],time=i;
}printf("%d\n",ans);printf("%02d%02d%02d",6+time/3600,time%3600/60,time%60);
return 0;
}