思路

没啥思考过程,照着题目跑bfs就过了。
大概就是跑的时候记格子的花费和是否用过魔法。
记录颜色时+1是因为比较方便区分白色。剪枝直接把同一格子花费大的剪掉就行了。
正确性的大概考虑:若经过同一格子两次,用魔法的状态肯定是一样的,并且金币只会递增。(不知所云)

代码

#include<bits/stdc++.h>
#define debug(x) cout<<"x="<<x<<endl
#define int long long
using namespace std;
const int maxn=1e5+7;
const int mod=1e9+7;
typedef long long ll;

//ifstream mycin("in.txt");
//ofstream mycout("out.txt");

int xx[]={0,0,1,-1},yy[]={1,-1,0,0};

inline void read(int &data){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    data=x*f;
}

struct node{
    int x,y,cost,used;
}; 

int m,n,cst[105][105],mp[105][105],used[105][105];
queue<node>q;

void bfs(){
    q.push((node){1,1,0,0});
    while(!q.empty()){
        node fro=q.front();
        q.pop();
        if(fro.x<1||fro.y<1||fro.x>m||fro.y>m) continue;
        if(fro.cost>=cst[fro.x][fro.y]) continue;
        cst[fro.x][fro.y]=fro.cost; //记录最小的花费 
        for(int d=0;d<4;d++){
            int dx=fro.x+xx[d],dy=fro.y+yy[d];
            if(mp[fro.x][fro.y]==mp[dx][dy]&&mp[dx][dy]) q.push((node){dx,dy,fro.cost,0});
            //有颜色且颜色相同 
            if(fro.used==mp[dx][dy]&&mp[dx][dy]) q.push((node){dx,dy,fro.cost,0});
            if(mp[fro.x][fro.y]!=mp[dx][dy]){
                if(mp[dx][dy]==0&&!fro.used){ //走去白色格子
                    q.push((node){dx,dy,fro.cost+2,mp[fro.x][fro.y]}); //下一个格子没有魔法 
                }else{ //红走黄、黄走红
                    q.push((node){dx,dy,fro.cost+1,0}); 
                }
            }
        }
    }
}

signed main(){
    int x,y,c;
    read(m);read(n);
    for(int i=1;i<=m;i++){
        for(int j=1;j<=m;j++){
            cst[i][j]=0x3f3f3f3f; //最小需要的花费
            mp[i][j]=0;//无颜色 
        }
    }
    for(int i=1;i<=n;i++){
        read(x);read(y);read(c);
        mp[x][y]=c+1; //地图 
    }
    bfs();
    /*
    for(int i=1;i<=m;i++){
        for(int j=1;j<=m;j++){
            cout<<cst[i][j]<<" ";
        }
        cout<<endl;
    }
    */
    if(cst[m][m]==0x3f3f3f3f) cout<<-1<<endl;
    else cout<<cst[m][m]<<endl;
    return 0;
}