首页 > 代码库 > USACO 2017 FEB Gold visitfj 最短路

USACO 2017 FEB Gold visitfj 最短路

  题意

    有一幅n*n的方格图,n <= 100,每个点上有一个值。从(1,1)出发,走到(n,n),只能走四联通。每走一步花费t,每走三步需要花费走完三步后到达格子的值。求最小花费的值。

  拆点,dis[i][j]表示到达第i个点时走的总步数模3等于j时的最小花费值。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>

using namespace std;

const int maxn = 105;
const int INF = 0x3fffffff;
int n, t, w[maxn][maxn];
struct Node
{
    int x, y, z;
    Node (int x = 0, int y = 0, int z = 0):
        x(x), y(y), z(z) {}
};
queue <Node> q;
int dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0};
int dis[maxn][maxn][3];
bool vis[maxn][maxn][3];

int main()
{
    freopen("visitfj.in", "r", stdin);
    freopen("visitfj.out", "w", stdout);
    scanf("%d %d", &n, &t);
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j)
            scanf("%d", &w[i][j]);
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j)
            for (int k = 0; k < 3; ++k)
                dis[i][j][k] = INF, vis[i][j][k] = false;
    dis[1][1][0] = 0;
    vis[1][1][0] = true;
    q.push(Node(1, 1, 0));
    while (!q.empty())
    {
        Node now = q.front();
        vis[now.x][now.y][now.z] = false;
        q.pop();
        for (int i = 0; i < 4; ++i)
        {
            int x = now.x+dx[i], y = now.y+dy[i], z = (now.z+1)%3;
            if (x < 1 || y < 1 || x > n || y > n)
                continue ;
            if (dis[x][y][z] > dis[now.x][now.y][now.z]+t+((z == 0) ? w[x][y] : 0))
            {
                dis[x][y][z] = dis[now.x][now.y][now.z]+t+((z == 0) ? w[x][y] : 0);
                if (!vis[x][y][z])
                    vis[x][y][z] = true, q.push(Node(x, y, z));
            }
        }
    }
    printf("%d\n", min(dis[n][n][0], min(dis[n][n][1], dis[n][n][2])));
    return 0;
}

 

USACO 2017 FEB Gold visitfj 最短路