链接:https://ac.nowcoder.com/acm/problem/16423
来源:牛客网
题目描述
有一个m × m的棋盘,棋盘上每一个格子可能是红色、黄色或没有任何颜色的。你现在要从棋盘的最左上角走到棋盘的最右下角。
任何一个时刻,你所站在的位置必须是有颜色的(不能是无色的),你只能向上、下、左、右四个方向前进。当你从一个格子走向另一个格子时,如果两个格子的颜色相同,那你不需要花费金币;如果不同,则你需要花费 1 个金币。
另外,你可以花费 2 个金币施展魔法让下一个无色格子暂时变为你指定的颜色。但这个魔法不能连续使用,而且这个魔法的持续时间很短,也就是说,如果你使用了这个魔法,走到了这个暂时有颜色的格子上,你就不能继续使用魔法;只有当你离开这个位置,走到一个本来就有颜色的格子上的时候,你才能继续使用这个魔法,而当你离开了这个位置(施展魔法使得变为有颜色的格子)时,这个格子恢复为无色。
现在你要从棋盘的最左上角,走到棋盘的最右下角,求花费的最少金币是多少?
输入描述:
数据的第一行包含两个正整数 m,n,以一个空格分开,分别代表棋盘的大小,棋盘上有颜色的格子的数量。 接下来的 n 行,每行三个正整数 x,y,c,分别表示坐标为(x,y)的格子有颜色 c。其中 c=1代表黄色,c=0 代表红色。相邻两个数之间用一个空格隔开。棋盘左上角的坐标为(1,1),右下角的坐标为(m, m)。 棋盘上其余的格子都是无色。保证棋盘的左上角,也就是(1,1)一定是有颜色的。输出描述:
输出一行,一个整数,表示花费的金币的最小值,如果无法到达,输出-1。
这题可以用BFS+优先队列。
对于每一步有以下几种情况:
下一步走红色:如果当前颜色是黄色,那总花费(val)+1, 如果当前颜色是红色,val不变
下一步走黄色:如果当前颜色是红色,那val+1, 如果当前颜色是黄色,val不变
下一步走无色:如果当前颜色是红色,我们把下一步无色变红色,val+2, 把无色变黄色,val+3
如果当前颜色是黄色,我们把下一步无色变黄色,val+2, 把无色变红色,val+3
我们每走一步就把当前的情况存入优先队列里,按当前val的值从小到大排序,当优先队列最先弹出来的坐标为(m,m)的值时,该val一定是所有到(m,m)情况中最小的。
同时,由于变色的操作不能连续使用,所以我们应该开个变量记录上一步是否变了色,代码如下。
代码:
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N = 105;
struct node{
int x, y, col, val, status; //记录坐标,当前格子的颜色,当前的花费,以及上一步是否变色的状态:0-没变,1-变了
bool operator < (const node& a) const
{
return val > a.val;
}
};
int px[] = {0, 0, -1, 1};
int py[] = {1, -1, 0, 0};
priority_queue<node> q;
int Map[N][N], fg[N][N] {0}; //存图和标记该格子是否走过
int res = 0;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int m, n;
cin >> m >> n;
memset(Map, -1, sizeof(Map)); //初始化为-1,-1表示无色的格子
for(int i=0; i<n; i++)
{
int x, y, z;
cin >> x >> y >> z;
Map[x][y] = z; //存图
}
q.push({1, 1, Map[1][1], 0, 0});//初始状态,没有变色
int ret = 0; //标记是否能够到达(m,m)
while(!q.empty())
{
node k = q.top();
if(k.x==m && k.y==m) //当到达时
{
res = k.val;
ret = 1; //能够到达时标记
break;
}
q.pop();
for(int i=0; i<4; i++)
{
int x = k.x + px[i];
int y = k.y + py[i];
if(x>0 && y>0 && x<=m && y<=m && !fg[x][y])
{
if(Map[x][y]==0)
q.push({x, y, 0, (k.col==0?k.val:k.val+1), 0}), fg[x][y] = 1;
if(Map[x][y]==1)
q.push({x, y, 1, (k.col==1?k.val:k.val+1), 0}), fg[x][y] = 1;
if(Map[x][y]==-1 && !k.status)
{
q.push({x, y, 0, (k.col==0?k.val+2:k.val+3), 1});
q.push({x, y, 1, (k.col==1?k.val+2:k.val+3), 1});
fg[x][y] = 1;
}
}
}
}
if(ret)
cout << res << endl;
else cout << -1 << endl;
return 0;
}