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) (2∗i,2∗i+2),(2∗j,2∗j+2),我们可以沿着每个格子的边沿走,如果碰到圆弧,我们可以从 ( 2 ∗ i , 2 ∗ j + 1 ) (2*i,2*j+1) (2∗i,2∗j+1) 走到 ( 2 ∗ i + 1 , 2 ∗ j + 2 ) (2*i+1,2*j+2) (2∗i+1,2∗j+2) 或者从 ( 2 ∗ i + 1 , 2 ∗ j ) (2*i+1,2*j) (2∗i+1,2∗j) 走到 ( 2 ∗ i + 2 , 2 ∗ j + 1 ) (2*i+2,2*j+1) (2∗i+2,2∗j+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;
}