题意
给出一个 的方格,其中有一些格子上有颜色。我们从(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]);
}