CF709B Checkpoints 题解

解析

在该题目中,经过其中 \(n-1\) 个点说明要去掉一个点不走

要求经过 \(n-1\) 个点的最小距离,只需计算到最左边和最右边的最短距离即可,因为只要到达这两个点,就意味着其间所有的点全部都经过了一遍,符合题意。

那么“去掉一个点不走”,需要去掉哪一个点呢?这个问题可分为两种情况:

  1. 去掉最左右两点
  2. 去掉它们之间的点

根据上面的推论,只有最左右两点影响最终结果,所以只有去掉最左右两点才可能得到最小行走距离,故只需要对比去掉左右那个点得到的行走距离,就能得到答案。

具体实现

我们可以使用变量 right1right2 和变量 left1left2 来分别计算点 \(a\) 往右走的最大、次大距离和往左走的最大、次大距离。

这样,最后只需要计算去掉 right1 或去掉 left1 得到的答案即可。

注意,先往左走和先往右走得到的答案是不同的,故需要再次判断。

\(\texttt{\textcolor{Green}{Accepted} 代码}\)

#include<cstdio>
#include<algorithm>
using namespace std;

int n,a;
int left1,left2;	//分别是a往左第一大的距离和第二大的距离
int right1,right2;	//分别是a往右第一大的距离和第二大的距离
int ans;

int MIN(int x1,int x2,int x3,int x4)	//四个数的最小值函数 
{
	return min(min(x1,x2),min(x3,x4));
}
int main()
{
	scanf("%d%d",&n,&a);
	for(int i=1;i<=n;i++)
	{
		int tmp;
		scanf("%d",&tmp);
		if(tmp>a)	//tmp在a右边 
		{
			if(tmp-a>right1)
			{
				right2=right1;
				right1=tmp-a;
			}
			else if(tmp-a>right2)
				right2=tmp-a;
			//更新right1和right2 
		}
		if(tmp<a)	//tmp在a左边 
		{
			if(a-tmp>left1)
			{
				left2=left1;
				left1=a-tmp;
			}
			else if(a-tmp>left2)
				left2=a-tmp;
			//更新left1和left2 
		}
	}
	ans=MIN(left2*2+right1,right1*2+left2,left1*2+right2,right2*2+left1);
	//计算最最小总行走距离
	printf("%d\n",ans);
	return 0;
}

2022-04-10 21:00 撰写于洛谷,2025-08-25 17:05 迁移至博客园。

posted @ 2025-08-25 17:06  Jerrycyx  阅读(11)  评论(0)    收藏  举报