hihoCoder1290. Demo Day

来源:互联网 发布:网络通缉犯在逃人员 编辑:程序博客网 时间:2024/06/06 07:48

题目来源:http://hihocoder.com/problemset/problem/1290

 

    题目大意是,给一个 N*M 的迷宫,输入给出每个位置是否有障碍(用b表示),把机器人放在左上角(0,0)的位置,目标是到达右下角(n-1, m-1)。机器人只能向右或向下行动,碰到障碍就改变方向,初始方向向右,问最少需要改变几个位置的障碍(没有b的可以增加b,有b的可以去掉b)。

    本题很容易想到用动态规划的方法去做,大概思路是,到达当前位置maze[i][j],只能从两个地方移动得到:maze[i-1][j]maze[i][j-1],取两者的较小即可。dp表需要记录到达每个位置所改变的障碍物,需要记录到达每个位置的方向。

    表的数据结构如下:

struct DP{int cnt, orient;//改变障碍物计数, 方向(0:either, 1:right, 2:down)};

    dp[i-1][j](上侧点)进行讨论,如果dp[i-1][j].orient == 1,则需要知道maze[i-1][j+1]是否存在障碍;如果dp[i-1][j].orient == 0 or 2,则 route[0] = dp[i-1][j].cnt.

    对dp[i][j-1](左侧点)进行讨论,如果dp[i-1][j].orient== 2,则需要知道maze[i+1][j-1]是否存在障碍;如果dp[i][j-1].orient == 0 or 1,则route[1] = dp[i][j-1].cnt.

    dp[i][j].cnt = min(route[0], route[1]),并设置到达dp[i][j]的方向,最后需要查看maze[i][j]是否存在障碍,如果有,dp[i][j].cnt++.

    这里要当心数组越界问题,需要初始化dp[0][0] ~ dp[0][m-1]dp[1][0] ~ dp[n-1][0]的值,以及一个小技巧,在最右侧和最底端加上障碍,具体做法是在申请maze数组空间的时候,申请(N+1)*(M+1)的空间并将这些位置初始化为true(有障碍)。给出AC代码:

#include <bits/stdc++.h>#define  REP(i, n)  for (int i=0; i<int(n); ++i)using namespace std;struct DP{int cnt, orient;//改变障碍物计数,方向(0:either, 1:right, 2:down)}*dp;int main(){int n, m;cin >> n >> m;bool **maze = new bool*[n+1];DP **dp = new DP*[n];REP(i, n+1) maze[i] = new bool[m+1];//(n+1)*(m+1) mazeREP(i, n) dp[i] = new DP[m];char c;REP(i, n) {getchar();REP(j, m) {scanf("%c", &c);maze[i][j] = (c=='.') ? false : true;}}//initializedp[0][0].cnt = maze[0][0] ? 1 : 0;dp[0][0].orient = 1;//rightfor(int j = 1; j < m; j++){dp[0][j].orient = 1;dp[0][j].cnt = maze[0][j] ? dp[0][j-1].cnt+1 :dp[0][j-1].cnt;}dp[1][0].cnt = maze[0][1] ? dp[0][0].cnt+maze[1][0] :dp[0][0].cnt+maze[1][0]+1;dp[1][0].orient = 2;for(int i = 2; i < n; i++){dp[i][0].orient = 2;dp[i][0].cnt = maze[i][0] ? dp[i-1][0].cnt+1 :dp[i-1][0].cnt;}REP(i, n+1) maze[i][m] = true;//最右端和最下端添加阻挡REP(i, m+1) maze[n][i] = true;for(int i = 1; i < n; i++)//dp{for(int j = 1; j < m; j++){//dp[i][j] look for dp[i-1][j] and dp[i][j-1]int tmp[2];switch(dp[i-1][j].orient){case 1://right, 如果有阻挡,肯定向下运动;如果没有阻挡,添加阻挡tmp[0] = maze[i-1][j+1] ? dp[i-1][j].cnt :dp[i-1][j].cnt+1;break;case 0://either or downcase 2:tmp[0] = dp[i-1][j].cnt;break;}switch(dp[i][j-1].orient){case 2://downtmp[1] = maze[i+1][j-1] ? dp[i][j-1].cnt : dp[i][j-1].cnt+1;break;case 0://either or rightcase 1:tmp[1] = dp[i][j-1].cnt;break;}if(tmp[0] == tmp[1])dp[i][j].orient = 0;else if(tmp[0] < tmp[1])dp[i][j].orient = 2;elsedp[i][j].orient = 1;dp[i][j].cnt = min(tmp[0], tmp[1]);if(maze[i][j]) dp[i][j].cnt++;}}cout<<dp[n-1][m-1].cnt;return 0;}


0 0