列表

详情


NC20255. [SCOI2007]最优驾车DRIVE

描述

有n条南北方向的双向街道和n条东西方向的双向街道纵横交错。相邻街道(不管是哪个走向)的距离均为L英里。西南角交叉口的坐标为(1,1),东北角为(n,n)。在所有交叉口均可任意改变行驶方向。每条街道有它自己的最高速度限制,该限制对整条街道有效(不管行驶方向如何)。
你的任务是从交叉口(xs,ys)开车行驶到(xt,yt),要求只能在交叉口处改变速度,行驶过程中不得违反所在街道的速度限制,只能沿着路程最短的线路行驶,并且行驶时间在给定的闭区间[t1,t2]内。
车速以“每小时英里数”为单位,它必须是5的正整数倍。若车速为v,则每加仑汽油能行驶的英里数为80-0.03v2

输入描述

输入第一行为两个整数n, L, 
第二行包含n个正整数,从南到北描述n条东西走向的街道的速度限制,
第三行包 含n个正整数,从西到东描述n条南北走向的街道的速度限制。
第四行包含六个正整数xs, ys, xt, yt, t1, t2.

输出描述

如果无解,输出No,否则输出两行,分别描述最早到达的方案(若有多种方案,选择其中最省油的)和最省油的方案(如果有多种方案,选择其中最早到达的)。
每种方案用两个数表示,第一个数表示到达时刻(单位:分钟 ,向上取整);第二个数表示耗油量(单位:加仑,四舍五入保留两位小数)。

示例1

输入:

6 20
30 40 50 50 50 50
50 50 50 50 50 40
1 1 6 6 300 320

输出:

300 6.25
318 5.60

说明:

【样例说明】样例1的最快路线为以40英里/小时为速度匀速前进,路程为200英里,因此时间为5小时,每加仑
汽油可以行驶80-0.03*40*40=32英里,因此耗油量为200/32=6.25加仑。最省油路线是先以40英里/小时行驶120英
里,然后以35英里/小时行驶80英里,耗油量为120/32+80/(80-0.03*35*35)=5.60加仑。下图的路线可以同时满足
两种方案(其中第二种方案需要在(6,2)处改变速度)。

示例2

输入:

8 2
10 20 20 30 10 20 10 10
10 20 20 30 10 20 10 20
6 8 2 4 10 39

输出:

No

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 112ms, 内存消耗: 33132K, 提交时间: 2020-04-01 20:56:15

#include<cstdio>
#include<iostream>
#define eps 1e-8
using namespace std;
const int N=12,M=210010;
const double INF=1e15;
int n,L,lcm,lim;
int a[N],b[N],xs,ys,xt,yt,t1,t2,ans1=-1,ans2;
double f[2][N][M],w[N];
int gcd(int a,int b)
{
	return b?gcd(b,a%b):a;
}
int recover(int x)
{
	x*=12;
	return x/lcm+(x%lcm>0);
}
int main()
{
	scanf("%d%d",&n,&L);
	for(int i=1;i<=10;i++)
	w[i]=1.0*L/(80.0-0.75*i*i);
	for(int i=1;i<=n;i++)
	scanf("%d",&a[i]),a[i]/=5;
	for(int i=1;i<=n;i++)
	scanf("%d",&b[i]),b[i]/=5;
	int cc=0;
	for(int i=1;i<=n;i++)
	{
		if(cc<a[i]) cc=a[i];
		if(cc<b[i]) cc=b[i];
	}
	for(int i=lcm=1;i<=cc;i++)
	lcm=lcm*i/gcd(lcm,i);
	scanf("%d%d%d%d%d%d",&xs,&ys,&xt,&yt,&t1,&t2);
	lim=t2*lcm/12;
	if(xs>xt) swap(xs,xt),swap(ys,yt);
	if(ys>yt)
	{
		for(int i=1,j=n;i<j;i++,j--) swap(a[i],a[j]);
		ys=n-ys+1,yt=n-yt+1;
	 } 
	 for(int j=ys;j<=yt;j++)
	 for(int k=0;k<=lim;k++)
	 f[0][j][k]=INF;
	 f[0][ys][0]=0;
	 int p=0;
	 for(int i=xs;i<=xt;i++,p^=1)
	 {
	 	for(int j=ys;j<=yt;j++)
	 	for(int k=0;k<=lim;k++)
	 	f[p^1][j][k]=INF;
	 	for(int j=ys;j<=yt;j++)
	 	for(int k=0;k<=lim;k++)
	 	if(f[p][j][k]<INF)
	 	{
	 		if(j<yt)
	 		for(int x=b[i];x;x--)
	 		{
	 			int t=k+lcm/x*L;
	 			if(t<=lim)
	 			f[p][j+1][t]=min(f[p][j+1][t],f[p][j][k]+w[x]);
			 }
			 if(i<xt)
			 for(int x=a[j];x;x--)
			 {
			 	int t=k+lcm/x*L;
			 	if(t<=lim)
			 	f[p^1][j][t]=min(f[p^1][j][t],f[p][j][k]+w[x]);
			 }
		 }
	 }
	 for(int k=0;k<=lim;k++)
	 if(k*12>=t1*lcm&&f[p^1][yt][k]<INF)
	 {
	 	if(ans1<0) ans1=k;
	 	if(!ans2||f[p^1][yt][k]+eps<f[p^1][yt][ans2]) ans2=k;
	 }
	 if(ans1<0)
	 {
	 	printf("No");
	 	return 0;
	 }
	 printf("%d %.2f\n%d %.2f\n",recover(ans1),f[p^1][yt][ans1],
	 recover(ans2),f[p^1][yt][ans2]);
	 return 0;
}

上一题