Description
题目描述
有一个m × m的棋盘,棋盘上每一个格子可能是红色、黄色或没有任何颜色的。你现在要从棋盘的最左上角走到棋盘的最右下角。
任何一个时刻,你所站在的位置必须是有颜色的(不能是无色的), 你只能向上、 下、左、 右四个方向前进。当你从一个格子走向另一个格子时,如果两个格子的颜色相同,那你不需要花费金币;如果不同,则你需要花费 1 个金币。
另外, 你可以花费 2 个金币施展魔法让下一个无色格子暂时变为你指定的颜色。但这个魔法不能连续使用, 而且这个魔法的持续时间很短,也就是说,如果你使用了这个魔法,走到了这个暂时有颜色的格子上,你就不能继续使用魔法; 只有当你离开这个位置,走到一个本来就有颜色的格子上的时候,你才能继续使用这个魔法,而当你离开了这个位置(施展魔法使得变为有颜色的格子)时,这个格子恢复为无色。
现在你要从棋盘的最左上角,走到棋盘的最右下角,求花费的最少金币是多少?
输入格式:
数据的第一行包含两个正整数 m, n,以一个空格分开,分别代表棋盘的大小,棋盘上有颜色的格子的数量。
接下来的 n 行,每行三个正整数 x, y, c, 分别表示坐标为( x, y)的格子有颜色 c。
其中 c=1 代表黄色, c=0 代表红色。 相邻两个数之间用一个空格隔开。 棋盘左上角的坐标为( 1, 1),右下角的坐标为( m, m)。
棋盘上其余的格子都是无色。保证棋盘的左上角,也就是( 1, 1) 一定是有颜色的。
输出格式:
输出一行,一个整数,表示花费的金币的最小值,如果无法到达,输出-1。
Sample Input
输入样例#1:
5 7
1 1 0
1 2 0
2 2 1
3 3 1
3 4 0
4 4 1
5 5 0
输入样例#2:
5 5
1 1 0
1 2 0
2 2 1
3 3 1
5 5 0
Sample Output
输出样例#1:
8
输出样例#2:
-1
HINT
输入输出样例 1 说明
从( 1, 1)开始,走到( 1, 2)不花费金币
从( 1, 2)向下走到( 2, 2)花费 1 枚金币
从( 2, 2)施展魔法,将( 2, 3)变为黄色,花费 2 枚金币
从( 2, 2)走到( 2, 3)不花费金币
从( 2, 3)走到( 3, 3)不花费金币
从( 3, 3)走到( 3, 4)花费 1 枚金币
从( 3, 4)走到( 4, 4)花费 1 枚金币
从( 4, 4)施展魔法,将( 4, 5)变为黄色,花费 2 枚金币,
从( 4, 4)走到( 4, 5)不花费金币
从( 4, 5)走到( 5, 5)花费 1 枚金币
共花费 8 枚金币。
输入输出样例 2 说明
从( 1, 1)走到( 1, 2),不花费金币
从( 1, 2)走到( 2, 2),花费 1 金币
施展魔法将( 2, 3)变为黄色,并从( 2, 2)走到( 2, 3)花费 2 金币
从( 2, 3)走到( 3, 3)不花费金币
从( 3, 3)只能施展魔法到达( 3, 2),( 2, 3),( 3, 4),( 4, 3)
而从以上四点均无法到达( 5, 5),故无法到达终点,输出-1
数据规模与约定
对于 30%的数据, 1 ≤ m ≤ 5, 1 ≤ n ≤ 10。
对于 60%的数据, 1 ≤ m ≤ 20, 1 ≤ n ≤ 200。
对于 100%的数据, 1 ≤ m ≤ 100, 1 ≤ n ≤ 1,000。
好吧......上课考试时爆50了(早知道不要用SPFA......)
再改成暴力45分(......)
再检查,发现没有使用魔法的flag是0,而有魔法时的flag是0或1......然后爆40......
再看,发现主函数调用dfs进去flag竟然没有设成-1(悲剧了......)......
改成-1,A了。
代码:
#include <iostream>
#include <cstring>
#define SIZE 101
using namespace std;
int a[SIZE][SIZE], best[SIZE][SIZE], INF[1], n;
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
void dfs(int x, int y, int dis, int flag) // 暴力深搜
{
int i, r, c;
if (dis >= best[x][y])
{
return;
}
best[x][y] = dis;
if (~flag) // 有魔法
{
for (i = 0; i < 4; ++i)
{
r = x + dx[i];
c = y + dy[i];
if (((!r) || (r > n)) || ((!c) || (c > n)))
{
continue;
}
if (~a[r][c])
{
dfs(r, c, dis + ((flag == a[r][c]) ? 0 : 1), -1);
}
}
return;
}
for (i = 0; i < 4; ++i) // 没有魔法
{
r = x + dx[i];
c = y + dy[i];
if (((!r) || (r > n)) || ((!c) || (c > n)))
{
continue;
}
if (~a[r][c])
{
dfs(r, c, dis + ((a[x][y] == a[r][c]) ? 0 : 1), -1);
}
else
{
dfs(r, c, dis + 2, a[x][y]);
}
}
return;
}
int main(int argc, char** argv)
{
int m, x, y;
memset(a, -1, sizeof (a));
scanf("%d%d", &n, &m);
while (m--)
{
scanf("%d%d", &x, &y);
scanf("%d", &a[x][y]); // 不能用scanf("%d%d%d", &x, &y, &a[x][y])!会错!(快读x = read(), y = read(), a[x][y] = read()是可以的......)
}
memset(best, 127, sizeof (best));
memset(INF, 127, sizeof (INF));
dfs(1, 1, 0, -1);
if (best[n][n] == INF[0])
{
printf("-1");
}
else
{
printf("%d", best[n][n]);
}
return 0;
}