P3956 棋盘

题目描述

有一个m \times mm×m的棋盘,棋盘上每一个格子可能是红色、黄色或没有任何颜色的。你现在要从棋盘的最左上角走到棋盘的最右下角。

任何一个时刻,你所站在的位置必须是有颜色的(不能是无色的), 你只能向上、 下、左、 右四个方向前进。当你从一个格子走向另一个格子时,如果两个格子的颜色相同,那你不需要花费金币;如果不同,则你需要花费 1个金币。

另外, 你可以花费 2 个金币施展魔法让下一个无色格子暂时变为你指定的颜色。但这个魔法不能连续使用, 而且这个魔法的持续时间很短,也就是说,如果你使用了这个魔法,走到了这个暂时有颜色的格子上,你就不能继续使用魔法; 只有当你离开这个位置,走到一个本来就有颜色的格子上的时候,你才能继续使用这个魔法,而当你离开了这个位置(施展魔法使得变为有颜色的格子)时,这个格子恢复为无色。

现在你要从棋盘的最左上角,走到棋盘的最右下角,求花费的最少金币是多少?


本题是较为基础的搜索,代码入下:

 

#include<cstdio>
#include<cstring>
#include<cmath>
#define inf 0x7fffffff
using namespace std;
int fx[4] = {-1, 0, 1, 0}; 
int fy[4] = {0, -1, 0, 1}; 
int f[110][110];
int mp[110][110]; 
int m, n, ans = inf;
void dfs(int x, int y, int sum, bool frog)
{
    if(x < 1 || y < 1 || x > m || y > m) return;
    if(sum >= f[x][y]) return;
    f[x][y] = sum;
    if(x==m && y==m) 
    {
        if(sum < ans) ans = sum;  //更新最小值
        return;
    }
    for(int i = 0; i < 4; ++i)
    {
        int xx = x + fx[i];
        int yy = y + fy[i];
        if(mp[xx][yy]) //如果有颜色
        {
            if(mp[xx][yy] == mp[x][y]) //如果颜色一样,无需花费
                 dfs(xx, yy, sum, false); 
            else dfs(xx, yy, sum+1, false);  //如果颜色不一样,花费一枚金币
        }  
        else  //如果无颜色
        {
            if(!frog)  //判断是否使用了魔法
            {
                mp[xx][yy] = mp[x][y]; 
                dfs(xx, yy, sum+2, true);  //标记为true 
                mp[xx][yy] = 0;  //回溯
            }
        }
    }
}
int main()
{
    memset(f, 0x7f, sizeof(f));
    scanf("%d %d", &m, &n);
    for(int i = 1; i <= n; ++i)
    {
        int x, y, c;
        scanf("%d %d %d", &x, &y, &c);
        mp[x][y] = c + 1;
    }
    dfs(1, 1, 0, false);
    printf("%d", ans==inf ? -1 : ans);
    return 0;
}

本题使用了深度优先搜索,我不会广搜,每进行一次搜索就更新一遍最小值,最后输出该值。

代码与一般的深搜差别不是很大,一些重要的地方已经做了注释。相信大家都能理解。

posted @ 2020-07-31 11:44  Na2S2O3  阅读(130)  评论(1编辑  收藏  举报