此题大意是n个车,每车重为w[i],最大速度v[i],已知桥长len,限重wei,求所有车通过桥的时间
首先想到背包,但身为一名蒟蒻并没有想到要怎么做,于是选用区间型DP
对于一个区间第i辆车到第j辆车,过桥的时间是len/min(v[i]~v[j]),且w[i]+……+w[j]<=wei
于是此题变得十分简单:首先对于任意区间[i,j]求出其中的最小速度,并用前缀和计算其重量和。
易得状态转移方程:f[i]=min(f[i],f[j-1]+len/ans[j][i]);
其中,f[i]表示第1辆车到第i辆车的最小通过时间,ans[i][j]表示已经预处理好的区间[i,j]中的最小速度。
形式化的讲,就是枚举区间[1,i]的中间点来维护此区间的最小值。
记住浮点数的精度问题
直接上代码:
#include <bits/stdc++.h>
using namespace std;
double f[1001];
long long len,wei,n,w[1001],v[1001],sum[1001],ans[1001][1001];
int main ()
{
cin >> wei >> len >> n;
for (int i=1;i<=n;++i){
cin >> w[i] >> v[i];
sum[i]=sum[i-1]+w[i];
ans[i][i]=v[i];
}
for (int i=1;i<n;++i)
for(int j=i+1;j<=n;++j)
ans[i][j]=min(v[j],ans[i][j-1]);
for (int i=1;i<=n;++i)
{
f[i]=(double)len/v[i]+f[i-1];
for (int j=i-1;j>=1;--j){
if (sum[i]-sum[j-1]<=wei)
f[i]=min(f[i],f[j-1]+(double)len/ans[j][i]);
else break;
}
}
printf("%.1lf",f[n]*60);
return 0;
}
ps:由于作者是一名资深蒟蒻,有错误也是不可避免的事,所以欢迎大家指出错误,我也会改正的,谢谢。