CCPC-Wannafly Winter Camp Day4 Div1 - 夺宝奇兵 - [简单思维题]

题目链接:https://zhixincode.com/contest/18/problem/A?problem_id=259

题目描述

wls正在玩一个寻宝游戏。

宝藏一共有 $n$ 种,都藏在一个 $m$ 行 $m$ 列的网格中。

每种宝藏都恰好有两个。

wls只能沿着网格走(上下左右四个方向)。

他想依次获得 $1...n$ 类宝藏,然后再以 $n...1$ 的顺序获得剩下的宝藏。

wls可以从任意点出发。

当wls到达某个宝藏的位置时,他可以选择取或不取这个宝藏。

请问他最少要移动多少距离?

输入描述

第一行两个整数 $n$,$m$。

接下来 $n$ 组,每组两行表示一类宝藏,每行两个整数 $x$,$y$ 表示一个宝藏的坐标。

$1≤n,m≤100000$
$1≤x,y≤m$

输出描述

一行一个整数表示答案。

题解:

将问题转换为两个人同时从第 $1$ 种宝藏出发,沿着 $1~n$ 的顺序拿宝藏。

假设第 $1$ 种宝藏分别为 $1a$ 和 $1b$,第 $2$ 种宝藏也分别为 $2a,2b$,那么只有两种选择 $1a → 2a, 1b → 2b$ 或者 $1a → 2b, 1b → 2a$,选择路程更短的就好了,因为不管当前怎么选择,对之后都没有任何影响。

最后再加个 $na$ 到 $nb$ 之间的路程就好了。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int n,m;
struct P{
    int x,y;
}p[maxn][2];
ll dist(P a,P b)
{
    return (ll)abs(a.x-b.x)+abs(a.y-b.y);
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&p[i][0].x,&p[i][0].y);
        scanf("%d%d",&p[i][1].x,&p[i][1].y);
    }

    ll ans=0;
    for(int i=2;i<=n;i++)
    {
        ans+=min(dist(p[i-1][0],p[i][0])+dist(p[i-1][1],p[i][1]),dist(p[i-1][0],p[i][1])+dist(p[i-1][1],p[i][0]));
    }
    cout<<ans+dist(p[n][0],p[n][1])<<endl;
}

猜你喜欢

转载自www.cnblogs.com/dilthey/p/10383355.html