ICPC Northwestern European Regional Programming Contest D Delft Distance

ICPC Northwestern European Regional Programming Contest D Delft Distance

题面描述:

给你一个 n × m n\times m n×m的矩阵,矩阵的包含的元素为{ ′ X ′ , ′ O ′ 'X','O' X,O}, O O O 代表该格的图形为圆,而 X X X代表该格图形为正方形,每一个格子的长度为 10 10 10.你可以沿着每个格子的边缘或者圆的边沿走,求从左上角走到右下角的最短路径

基本思路:

将每个格子拆成 2 × 2 2\times 2 2×2 的小方格,那么 a i j a_{ij} aij ( 从 0 开始 ) (从0开始) (0开始)涉及到的坐标范围是 ( 2 ∗ i , 2 ∗ i + 2 ) , ( 2 ∗ j , 2 ∗ j + 2 ) (2*i,2*i+2),(2*j,2*j+2) (2i,2i+2),(2j,2j+2),我们可以沿着每个格子的边沿走,如果碰到圆弧,我们可以从 ( 2 ∗ i , 2 ∗ j + 1 ) (2*i,2*j+1) (2i,2j+1) 走到 ( 2 ∗ i + 1 , 2 ∗ j + 2 ) (2*i+1,2*j+2) (2i+1,2j+2) 或者从 ( 2 ∗ i + 1 , 2 ∗ j ) (2*i+1,2*j) (2i+1,2j) 走到 ( 2 ∗ i + 2 , 2 ∗ j + 1 ) (2*i+2,2*j+1) (2i+2,2j+1)

另外,我们发现最贪心的方法是只向右或向下走,所以我们可以进行 d p dp dp,对走到某个坐标所需要的最小路程进行 d p dp dp 即可

代码

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;

#define Paddi ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int N = 1500;
const double pi = acos(-1.0);
char maze[N][N];
int n, m;
double dp[N][N];

signed main()
{
    Paddi;
    double quart = 2.5 * pi, len = 5.0;
    cin >> n >> m;

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
            cin >> maze[i][j];
    }

    for (int i = 0; i <= 2 * n + 10; i++)
    {
        for (int j = 0; j <= 2 * m + 10; j++)
            dp[i][j] = 1e18;
    }
    dp[0][0] = 0;

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            if (maze[i][j] == 'X')
            {
                dp[2 * i + 1][2 * j] = min(dp[2 * i + 1][2 * j], dp[2 * i][2 * j] + len);
                dp[2 * i + 2][2 * j] = min(dp[2 * i + 2][2 * j], dp[2 * i + 1][2 * j] + len);
                dp[2 * i + 2][2 * j + 1] = min(dp[2 * i + 2][2 * j + 1], dp[2 * i + 2][2 * j] + len);
                dp[2 * i + 2][2 * j + 2] = min(dp[2 * i + 2][2 * j + 2], dp[2 * i + 2][2 * j + 1] + len);

                dp[2 * i][2 * j + 1] = min(dp[2 * i][2 * j + 1], dp[2 * i][2 * j] + len);
                dp[2 * i][2 * j + 2] = min(dp[2 * i][2 * j + 2], dp[2 * i][2 * j + 1] + len);
                dp[2 * i + 1][2 * j + 2] = min(dp[2 * i + 1][2 * j + 2], dp[2 * i][2 * j + 2] + len);
                dp[2 * i + 2][2 * j + 2] = min(dp[2 * i + 2][2 * j + 2], dp[2 * i + 1][2 * j + 2] + len);
            }
            else if (maze[i][j] == 'O')
            {
                dp[2 * i + 1][2 * j] = min(dp[2 * i + 1][2 * j], dp[2 * i][2 * j] + len);
                dp[2 * i + 2][2 * j + 1] = min(dp[2 * i + 2][2 * j + 1], dp[2 * i + 1][2 * j] + quart);
                dp[2 * i + 2][2 * j] = min(dp[2 * i + 2][2 * j], dp[2 * i + 1][2 * j] + len);
                dp[2 * i + 2][2 * j + 1] = min(dp[2 * i + 2][2 * j + 1], dp[2 * i + 2][2 * j] + len);
                dp[2 * i + 2][2 * j + 2] = min(dp[2 * i + 2][2 * j + 2], dp[2 * i + 2][2 * j + 1] + len);

                dp[2 * i][2 * j + 1] = min(dp[2 * i][2 * j + 1], dp[2 * i][2 * j] + len);
                dp[2 * i + 1][2 * j + 2] = min(dp[2 * i + 1][2 * j + 2], dp[2 * i][2 * j + 1] + quart);
                dp[2 * i][2 * j + 2] = min(dp[2 * i][2 * j + 2], dp[2 * i][2 * j + 1] + len);
                dp[2 * i + 1][2 * j + 2] = min(dp[2 * i + 1][2 * j + 2], dp[2 * i][2 * j + 2] + len);
                dp[2 * i + 2][2 * j + 2] = min(dp[2 * i + 2][2 * j + 2], dp[2 * i + 1][2 * j + 2] + len);
            }
        }
    }

    // 输出答案
    double an = dp[2 * n][2 * m];
    cout << fixed << setprecision(10) << an << endl;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值