P3956 棋盘

pjT3翻车了,怕是连pj组都不如

这道题一看上去就是用bfs的啊,用dfs还怕爆栈。

然后就手动地打了个非常暴力的bfs,只拿到了25pts。

翻了题解才知道这个东西居然还能用spfa!

总结性话语:搜索题不会做的,试着转换成图论题,用图论题的思路解决暴力模拟也许会更方便


所以我们可以类似于spfa,建立一个vis数组和dist数组。

如何记录状态?

当前行列肯定要记的,然后就要考虑那个花两块钱变色的东西。

不难发现再开一维记录当前位置的颜色即可,不需要去更改原矩阵。当原颜色与当前颜色不一样的时候就说明我使用了膜法。

有一个贪心的做法:当我下一步是一个无颜色的格子,那么最优的是直接指定为同样颜色,这样只要花两块钱,不然要花三块钱。

对于不同的颜色,注意去分别判断,用类似于spfa的方法去更新。

所以就完事了。最后输出一下std::min(dist[n][n][0], dist[n][n][1])就可以了。

代码:

#include<cstdio>
#include<cstring>
#include<queue>
const int maxn = 105;
const int dx[] = {0, 0, 1, -1};
const int dy[] = {1, -1, 0, 0};
struct Nodes
{
    int x, y, col;
    Nodes(int x, int y, int col):x(x), y(y), col(col){}
};
int G[maxn][maxn];
int dist[maxn][maxn][2];
bool vis[maxn][maxn][2];
int n, m;

int main()
{
    memset(dist, 0x3f, sizeof dist);
    memset(G, -1, sizeof G);
    scanf("%d%d", &n, &m);
    while(m--)
    {
        int x, y, z; scanf("%d%d%d", &x, &y, &z);
        G[x][y] = z;
    }
    std::queue<Nodes> q;
    dist[1][1][G[1][1]] = 0;
    q.push(Nodes(1, 1, G[1][1])); vis[1][1][G[1][1]] = true;
    while(!q.empty())
    {
        Nodes u = q.front(); q.pop();
        int x = u.x, y = u.y, col = u.col, res = dist[x][y][col];
        vis[x][y][col] = false;
        for(int i = 0; i < 4; i++)
        {
            int nx = x + dx[i], ny = y + dy[i];
            if(nx >= 1 && nx <= n && ny >= 1 && ny <= n)
            {
                if(G[nx][ny] == -1)
                {
                    if(G[x][y] == -1) continue;
                    if(res + 2 < dist[nx][ny][col])
                    {
                        dist[nx][ny][col] = res + 2;
                        if(!vis[nx][ny][col])
                        {
                            q.push(Nodes(nx, ny, col));
                            vis[nx][ny][col] = true;
                        }
                    }
                }
                else if(G[nx][ny] != col)
                {
                    if(res + 1 < dist[nx][ny][G[nx][ny]])
                    {
                        dist[nx][ny][G[nx][ny]] = res + 1;
                        if(!vis[nx][ny][G[nx][ny]])
                        {
                            q.push(Nodes(nx, ny, G[nx][ny]));
                            vis[nx][ny][G[nx][ny]] = true;
                        }
                    }
                }
                else if(G[nx][ny] == col)
                {
                    if(res < dist[nx][ny][G[nx][ny]])
                    {
                        dist[nx][ny][G[nx][ny]] = res;
                        if(!vis[nx][ny][G[nx][ny]])
                        {
                            q.push(Nodes(nx, ny, G[nx][ny]));
                            vis[nx][ny][G[nx][ny]] = true;
                        }
                    }
                }
            }
        }
    }
    int ans;
    if(G[n][n] != -1) ans = dist[n][n][G[n][n]];
    else ans = std::min(dist[n][n][0], dist[n][n][1]);
    if(ans != 0x3f3f3f3f) printf("%d\n", ans);
    else printf("-1\n");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Garen-Wang/p/9833329.html