洛谷_3956 棋盘

题意

给出一个 m m 的方格,其中有一些格子上有颜色。我们从(1,1)出发,终点是(n,n)。我们每次要站在有颜色的格子上,如果我们接下来走的格子和现在格子的颜色一致,那么就不用花费金币,如果颜色不一致就要花费1金币,如果没有颜色,可以使用魔法来让这个格子变成任意颜色,花费2金币(不能连续使用魔法)。求走到终点花费的最少金币。

思路

记忆化搜索。用一个数组记录走到这个格子的最少金币,然后每次搜索时就可以剪枝。搜索按正常的打就好了。

代码

#include<cstdio>
#include<cstring>
using namespace std;
int m,n,a,b,c,map[105][105],ans[105][105],v[105][105];
short dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
void dfs(int x,int y,int f,int s)
{
    if (ans[x][y]<=s) return;//剪枝
    ans[x][y]=s;//记录答案
    int xx,yy;
    for (int i=0;i<4;i++)
    {
        xx=x+dx[i];yy=y+dy[i];
        if (!map[xx][yy]&&f||(xx<1||xx>n||yy<1||yy>n)||v[xx][yy]) continue;//不能连续使用魔法,在范围内
        v[xx][yy]=1;
        if (map[xx][yy]==map[x][y]) dfs(xx,yy,0,s);//颜色相同直接走
        else if (!map[xx][yy])//使用魔法
        {
            map[xx][yy]=map[x][y];
            dfs(xx,yy,1,s+2);
            map[xx][yy]=0;
        }
        else dfs(xx,yy,0,s+1);//颜色不同消耗1金币
        v[xx][yy]=0;
    }
}
int main()
{
    memset(ans,127/3,sizeof(ans));
    scanf("%d%d",&n,&m);
    while (m--)
    {
        scanf("%d%d%d",&a,&b,&c);
        map[a][b]=c+1;
    }
    dfs(1,1,0,0);
    if (ans[n][n]==707406378) printf("-1");
    else printf("%d",ans[n][n]);
}

猜你喜欢

转载自blog.csdn.net/SSL_hzb/article/details/81609343