【题解】 NOIP2012 提高组day1 T3 开车旅行(倍增 dfs 模拟) 70分做法

倍增没有学,不过我们可以通过模拟和dfs得到70分的部分分。

手写dis函数求两个城市距离=海拔差的绝对值。设一个km[i][2]的二维数组,来记录离i个城市距离最近和第二近的城市,要注意题目里有许多细节。例如距离相同时判断海拔低的城市更近。设m2 m1为0代表离i次近和最近的城市,循环城市i,再循环j(i+1 到 n),如果满足上述条件,就用j更新m1,m1更新m2。当然存在j不是最近但能更新次近的情况,用if处理即可。输入x0。第一问让我们求总路程不超过x0时从哪个城市出发a和b开车距离比值最小。可以通过dfs传四个参数模拟,s表示开始城市的编号,x表示该小a还是小b开车了(在之前的km数组里存过),da、db分别表示小A小B开车走过的距离。如果当前城市的前面没有合法的城市了或者da、db、s和to之间距离之和大于x0就停止。否则传入参数等于2时,代表小A开车,da+=dis(s,to),从to开始dfs,传入参数转化为另一种。利用这个dfs我们第一问可以枚举城市求出其da、db值,如果db==0并且比值为-1(代表正无穷),那么就该比较两者的海拔。若当前城市海拔高于ans海拔,更新ans。若db不为0,如果比值为-1就更新,如果比值不为-1的话,在da/db(double类型)<比值或等于比值、海拔更高的情况下更新ans,可以求出第一问。对于第二问,读入处罚城市和最大限度后,利用dfs函数求出da db 输出即可

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
int n,m;
int h[100100];
int q,x0;
int km[100100][3];
int dis(int x,int y)
{
	if(x==0||y==0) return (2e9)+1;
	return abs(h[x]-h[y]);
}
void dfs(int s,int x,int &da,int &db)
{
	int to=km[s][x];
	if(to==0) return ;
	int d=dis(s,to);
	if(da+db+d>x0) return;
	if(x==1)
	{
		db+=d;
		dfs(to,2,da,db);
	}
	if(x==2)
	{
		da+=d;
		dfs(to,1,da,db);
	}
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&h[i]);
	}
	for(int i=1;i<=n;i++)
	{
		int m1=0,m2=0;
		for(int j=i+1;j<=n;j++)
		{
			if(dis(m1,i)>dis(j,i)||(dis(m1,i)==dis(j,i)&&h[j]<h[m1]))
			{
				m2=m1;
				m1=j;
			}
			else
			{
				if(dis(m2,i)>dis(j,i)||(dis(m2,i)==dis(j,i)&&h[j]<h[m2]))
				{
					m2=j;
				}
			}
		}
		km[i][1]=m1;
		km[i][2]=m2;
	}
	scanf("%d",&x0);
	int ans=0;
	double ra=-1; //比值无穷大
	for(int i=1;i<=n;i++)
	{
		int da=0,db=0;
		dfs(i,2,da,db);
		if(db==0)
		{
			if(ra==-1&&h[i]>h[ans])
			{
				ans=i;
			}
		} 
		if(db!=0)
		{
			if(ra==-1||(1.0*da/db<ra||(1.0*da/db==ra&&h[i]>h[ans])))
			{
				ans=i;
				ra=1.0*da/db; 
			}
		}
	}
	cout<<ans<<endl;
	
	scanf("%d",&m);
	for(int i=1;i<=m;i++)
	{
		int si;
		scanf("%d%d",&si,&x0);
		int da=0,db=0;
		dfs(si,2,da,db);
		printf("%d %d\n",da,db);
	}
	
	//fclose(stdin);
	//fclose(stdout);
	return 0;
}


猜你喜欢

转载自blog.csdn.net/rem_inory/article/details/81047585