http://hihocoder.com/problemset/problem/1290
转载请注明出处:http://blog.csdn.net/acmhonor/article/details/51079224
记忆化搜索
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int inf = 100000005;
int n, m; //图的大小
int Move[2][2] = {{0, 1}, {1, 0}}; //移动向量
bool mapn[105][105]; //图,false表示空白, true 表示障碍物
int dp[2][105][105]; //方向,位置 走到右下最少需要改变多少格子
int Min(int a, int b)
{
if(a < b)
return a;
return b;
}
int Dfs(int dir, int x, int y) //求解当前机器人的方向是dir(0 表示向右,1表示向左), 机器人的位置是x, y 走到右下角需要改变最少的格子数
{
if(x == n - 1 && y == m - 1) //走到右下角
return 0;
if(dp[dir][x][y] != -1) //已经搜索过了,直接返回结果
return dp[dir][x][y];
dp[dir][x][y] = inf; //没有搜索过就初始化为最大
for(int i = 0; i < 2; i++){
int nx = x + Move[i][0]; //尝试移动
int ny = y + Move[i][1];
if(nx >= n || ny >= m) //出借
continue;
if(i == dir){ //没有改变方向
int temp = Dfs(i, nx, ny); //求解从方向是i位置是x, y走到右下角需要改变最少的格子数
if(mapn[nx][ny] == true){ //从(x, y) 到 (nx, ny) 但是 (nx, ny) 是障碍物所以改变(nx, ny)格子
temp ++; //修改的格子数 +1
}
dp[dir][x][y] = Min(dp[dir][x][y], temp); //取最小值
}
else{ //改变了方向
int temp = Dfs(i, nx, ny); //求解从方向是i位置是x, y走到右下角需要改变最少的格子数
int mx = x + Move[dir][0];
int my = y + Move[dir][1];
if(mapn[mx][my] == false){ //如果(mx, my) 不是是障碍物则把它变成障碍(否则不能改变方向)
temp ++; //修改的格子数 +1
}
if(mapn[nx][ny] == true){ //从(x, y) 到 (nx, ny) 但是 (nx, ny) 是障碍物所以改变(nx, ny)格子
temp ++; //修改的格子数 +1
}
dp[dir][x][y] = Min(dp[dir][x][y], temp); //取最小值
}
}
return dp[dir][x][y]; //返回结果
}
int main()
{
char str[105];
while(~scanf("%d%d", &n, &m)){
memset(dp, -1, sizeof(dp));
memset(mapn, true, sizeof(mapn));
for(int i = 0; i < n; i++){
scanf("%s", str);
for(int k = 0; k < m; k++){
if(str[k] == '.')
mapn[i][k] = 0;
}
}
printf("%d\n", Dfs(0, 0, 0));//求方向是0,位置是0, 0到右下角需要改变最少的格子数
}
return 0;
}