题目描述
有一个m imes mm×m的棋盘,棋盘上每一个格子可能是红色、黄色或没有任何颜色的。你现在要从棋盘的最左上角走到棋盘的最右下角。
任何一个时刻,你所站在的位置必须是有颜色的(不能是无色的), 你只能向上、 下、左、 右四个方向前进。当你从一个格子走向另一个格子时,如果两个格子的颜色相同,那你不需要花费金币;如果不同,则你需要花费 1个金币。
另外, 你可以花费 2 个金币施展魔法让下一个无色格子暂时变为你指定的颜色。但这个魔法不能连续使用, 而且这个魔法的持续时间很短,也就是说,如果你使用了这个魔法,走到了这个暂时有颜色的格子上,你就不能继续使用魔法; 只有当你离开这个位置,走到一个本来就有颜色的格子上的时候,你才能继续使用这个魔法,而当你离开了这个位置(施展魔法使得变为有颜色的格子)时,这个格子恢复为无色。
现在你要从棋盘的最左上角,走到棋盘的最右下角,求花费的最少金币是多少?
本题是较为基础的搜索,代码入下:
#include<cstdio> #include<cstring> #include<cmath> #define inf 0x7fffffff using namespace std; int fx[4] = {-1, 0, 1, 0}; int fy[4] = {0, -1, 0, 1}; int f[110][110]; int mp[110][110]; int m, n, ans = inf; void dfs(int x, int y, int sum, bool frog) { if(x < 1 || y < 1 || x > m || y > m) return; if(sum >= f[x][y]) return; f[x][y] = sum; if(x==m && y==m) { if(sum < ans) ans = sum; //更新最小值 return; } for(int i = 0; i < 4; ++i) { int xx = x + fx[i]; int yy = y + fy[i]; if(mp[xx][yy]) //如果有颜色 { if(mp[xx][yy] == mp[x][y]) //如果颜色一样,无需花费 dfs(xx, yy, sum, false); else dfs(xx, yy, sum+1, false); //如果颜色不一样,花费一枚金币 } else //如果无颜色 { if(!frog) //判断是否使用了魔法 { mp[xx][yy] = mp[x][y]; dfs(xx, yy, sum+2, true); //标记为true mp[xx][yy] = 0; //回溯 } } } } int main() { memset(f, 0x7f, sizeof(f)); scanf("%d %d", &m, &n); for(int i = 1; i <= n; ++i) { int x, y, c; scanf("%d %d %d", &x, &y, &c); mp[x][y] = c + 1; } dfs(1, 1, 0, false); printf("%d", ans==inf ? -1 : ans); return 0; }
本题使用了深度优先搜索,我不会广搜,每进行一次搜索就更新一遍最小值,最后输出该值。
代码与一般的深搜差别不是很大,一些重要的地方已经做了注释。相信大家都能理解。