P1594 护卫队
Posted hrj1
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1594 护卫队相关的知识,希望对你有一定的参考价值。
题目描述
护卫车队在一条单行的街道前排成一队,前面河上是一座单行的桥。因为街道是一条单行道,所以任何车辆都不能超车。桥能承受一个给定的最大承载量。为了控制桥上的交通,桥两边各站一个指挥员。护卫车队被分成几个组,每组中的车辆都能同时通过该桥。当一组车队达到了桥的另一端,该端的指挥员就用电话通知另一端的指挥员,这样下一组车队才能开始通过该桥。每辆车的重量是已知的。任何一组车队的重量之和不能超过桥的最大承重量。被分在同一组的每一辆车都以其最快的速度通过该桥。一组车队通过该桥的时间是用该车队中速度最慢的车通过该桥所需的时间来表示的。问题要求计算出全部护卫车队通过该桥所需的最短时间值。
输入格式
输入文件第一行包含三个正整数(用空格隔开),第一个整数表示该桥所能承受的最大载重量(用吨表示);第二个整数表示该桥长度(用千米表示);第三个整数表示该护卫队中车辆的总数(n<1000)。接下来的几行中,每行包含两个正整数W和S(用空格隔开),W表示该车的重量(用吨表示),S表示该车过桥能达到的最快速度(用千米/小时表示)。车子的重量和速度是按车子排队等候时的顺序给出的。
输出格式
输出文件应该是一个实数,四舍五入精确到小数点后1位,表示整个护卫车队通过该桥所需的最短时间(用分钟表示)。
输入输出样例
100 5 10 40 25 50 20 50 20 70 10 12 50 9 70 49 30 38 25 27 50 19 70
75.0
这道题采用动态规划的思想。用f[i]表示前i辆车通过的最小时间;用vmin[i][j]表示第i辆车到第j辆车的最小速度;用sum[i]表示前i辆车的重量。动归式如下:
1.赋初值:f[i]=(double)len/v[i]+f[i-1];
2.如果第j辆车到第i辆车可以同时通过:
f[i]=min(f[i],f[j-1]+(double)len/vmin[j][i]);
得分:100
时间复杂度:O(N^2)
空间复杂度:O(3*N+N^2)
#include <iostream> #include <cstdio> using namespace std; int N, len, mw; long long W[1002], sum[1002]; double f[1002], lg2[1002]={-1}, S[1002][10]; inline int read(){ int s=0,w=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){ if(ch==‘-‘){ w=-1; } ch=getchar(); } while(ch>=‘0‘&&ch<=‘9‘){ s=s*10+ch-‘0‘; ch=getchar(); } return s*w; } double Query(int l, int r){ int lg=lg2[r-l+1]; return max(S[l][lg], S[r-(1<<lg)+1][lg]); } int main(){ mw=read(); len=read(); N=read(); for (int i=1; i<=N; i++) lg2[i]=lg2[i>>1]+1; for(int i=1; i<=N; i++){ W[i]=read(); S[i][0]=read(); f[i]=S[i][0]=(double)len/S[i][0]; sum[i]=W[i]+sum[i-1]; } for (int j=1; j<=lg2[N]; j++) for (int i=1; i+(1<<j)-1<=N; i++) S[i][j]=max(S[i][j-1], S[i+(1<<(j-1))][j-1]); for(int i=1; i<=N; i++){ f[i]+=f[i-1]; for(int j=i-1; j>=1; j--){ if (sum[i]-sum[j-1]<=mw){ f[i]=min(f[i], f[j-1]+Query(j, i)); } else break; } } printf("%.1lf", f[N]*60); return 0; }
以上是关于P1594 护卫队的主要内容,如果未能解决你的问题,请参考以下文章