版权声明:欢迎借鉴,谢绝抄搬。 https://blog.csdn.net/ssllyf/article/details/85099201
题目大意:
有一个M*M的棋盘,要从(1,1)到(m,m),中间有n个有颜色的格子,只能踩在有颜色的格子上,跳到不同颜色的格子要花费1元,可以将前方没颜色的格子变成自己要的格子,但要花费2元(走过去还要按上述规则花钱),走出变色出来的格子后,这个格子会变回无颜色,当棋盘上有变色出来的格子时,无法再变色,从(1,1)到(m,m)最少花多少钱?如果走不到,输出-1
解题方法:
这题我们可以用深搜,四个个数x,y,money,p,分别为行,列,用的钱,又没有变过色,在按照提议把每一种走法套进去,还要用一个a[i][j]来记录到(i,j)花费的钱最少是多少,当大于或等于这个数时退出,否则更新a
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
int n,ans,m,a[110][110],color[110][110];
const int dx[4]={1,0,-1,0};//四个方向
const int dy[4]={0,1,0,-1};//四个方向
void dfs(int x,int y,int money,int p)
{
int o;
if ((x==n)&&(y==n))//看看是否到结果
{
ans=min(ans,money);//求最小的
return;
}
if (a[x][y]<=money) return;//剪枝
else a[x][y]=money;//替换
if (money>ans) return;//剪枝
for (int i=0;i<4;i++)
if ((x+dx[i]>0)&&(x+dx[i]<=n)&&(y+dy[i]>0)&&(y+dy[i]<=n))//看看是否出界
{
if (color[x][y]==color[x+dx[i]][y+dy[i]])//颜色相同
{
o=color[x][y];//记录
if (p) color[x][y]=0;//如果变过色,要变回去
dfs(x+dx[i],y+dy[i],money,0);//用加money
color[x][y]=o;//再变回来
}
else if(color[x+dx[i]][y+dy[i]])//有颜色
{
o=color[x][y];//同上
if (p) color[x][y]=0;
dfs(x+dx[i],y+dy[i],money+1,0);//money+1
color[x][y]=o;
}
else if(!p)//要没变过
{
color[x+dx[i]][y+dy[i]]=color[x][y];//不需要考虑变哪种,如果下一步给钱的反过来还是要给钱,不用给就不用给
dfs(x+dx[i],y+dy[i],money+2,1);//money+2
color[x+dx[i]][y+dy[i]]=0;//清零
}
}
}
int main()
{
memset(a,127/3,sizeof(a));//因为要求最小的
ans=a[0][0];//直接复制过去
scanf("%d%d",&n,&m);
int x,y,c;
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&c);
color[x][y]=c+1;//要加1才能避免0的出现
}
dfs(1,1,0,0);
if (ans==a[0][0]) ans=-1;
printf("%d",ans);
}