我想从这道题开始展开对方向广搜各类题的总结;
普通的方向广搜就用单纯的队列然后根据题目的方向去搜就行;
但总有一些变形题在求最小值的时候,会限制或者是增加一些条件,使得一个点不能只单纯的遍历一次,或者说遍历玩这个点后还要进行折返之类的问题;
比如说这道题,这道题明显的要用广搜来写,网上很多题解也都是用广搜,至于颜色变换的地方也只是对是否入队的判断罢了,不是什么大问题。关键的地方就在于一个点从不同方向的地方遍历过来得到的所用的金钱是不同的。但广搜的弊端就在于这个点如果被遍历后就不能再被遍历了,如果继续遍历很容易超时或者超空间。所以这道题还要再引入贪心的思想。虽然还是进行遍历,但每次遍历开始的点必定是队列中金钱消耗量最少的点。
也就是说把队列换成优先队列,优先队列中排列顺序是所用金钱量从小到大,即可;
#include <bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxm=105;
int ans[maxm][maxm],sum[maxm][maxm];
bool flag[maxm][maxm];
int m,n;
struct node
{
int x,y,color,fund;
node(int x,int y,int color,int fund):x(x),y(y),color(color),fund(fund){}
bool operator <(const node &w)const
{
return fund>w.fund;
}
};
int dis[4][2]={1,0,0,1,-1,0,0,-1};
priority_queue<node> q;
int judge(int color,int pcolor)//黄1,红0,白-1,白黄-3,白红-2
{
if(color==1&&pcolor==1) return 0;//黄黄
else if(color==0&&pcolor==0) return 0;//红红
else if(color==0&&pcolor==1||color==1&&pcolor==0) return 1;//2,黄红,红黄
else if(color==-3&&pcolor==-1||color==-2&&pcolor==-1) return -1;//2,白黄白,白红白
else if(color==1&&pcolor==-1||color==0&&pcolor==-1) return 2;//2,黄白,红白
else if(color==-2&&pcolor==0) return 0;//1,白红红
else if(color==-2&&pcolor==1) return 1;//1,白红黄
else if(color==-3&&pcolor==1) return 0;//1,白黄黄
else if(color==-3&&pcolor==0) return 1;//1,白黄红
return 0;
}
void BFS()
{
q.push({1,1,ans[1][1],0});
sum[1][1]=0;
while(q.size())
{
node tmp=q.top();
q.pop();
int x=tmp.x,y=tmp.y;
if(flag[x][y]) continue;
flag[x][y]=true;
for(int i=0;i<4;i++)
{
int px=x+dis[i][0],py=y+dis[i][1];
if(px>=1&&px<=m&&py>=1&&py<=m&&flag[px][py]==false)
{
int color=tmp.color;
int t=judge(color,ans[px][py]);
if(t!=-1)
{
if(t==0) q.push({px,py,ans[px][py],tmp.fund+t});
else if(t==1) q.push({px,py,ans[px][py],tmp.fund+t});
else if(t==2)
{
if(ans[x][y]==0) q.push({px,py,-2,tmp.fund+t});
else if(ans[x][y]==1) q.push({px,py,-3,tmp.fund+t});
}
sum[px][py]=min(sum[px][py],tmp.fund+t);
}
}
}
}
}
int main()
{
memset(ans,-1,sizeof(ans));
memset(sum,INF,sizeof(sum));
cin>>m>>n;
for(int i=1;i<=n;i++)
{
int x,y,z;
cin>>x>>y>>z;
ans[x][y]=z;
}
BFS();
/*for(int i=1;i<=m;i++)
{
for(int j=1;j<=m;j++)
{
cout<<sum[i][j]<<" ";
}
cout<<endl;
}*/
if(flag[m][m]) cout<<sum[m][m]<<endl;
else cout<<-1<<endl;
return 0;
}