题目大意

一个MxN的矩阵,矩阵中的有些方格中有障碍物,有些没有,有一个机器人从左上角出发,它只能有两种移动方式:一直向右移动,直到遇到障碍物;一直向下移动,直到遇到障碍物。 
    现在可以将矩阵中的方格进行变换:如果方格中没有障碍物,则可以加入障碍物;如果方格中有障碍物,则可以清楚障碍物。求使得机器人可以从左上角移动到右下角的最少的方格变动个数。 
题目链接: demo_day

题目分析

搜索复杂度太高,由于机器人只能向右或者向下移动,这就可以考虑使用动态规划进行状态的转移。设状态 dp[i][j][0] 表示robot从左侧进入方格(i,j)所需要改变的最少的方格数;dp[i][j]1表示robot从上侧进入方格(i, j)时所需要改变的最少的方格数。

这道题目是微软的暑期实习在线笔试题,考试期间做的时候由于对c/c++中的运算符优先级没有掌握准确,left_min + (gMap[i - 1][j - 1] == 'b') 中没有加括号,导致结果出错。基础很重要啊! 运算优先级不确定的地方,加括号! 
另外,动态规划的初始值很重要,要仔细思考!

实现

  1. #include<iostream>
  2. #include<vector>
  3. #include<string>
  4. #include<algorithm>
  5. #include<unordered_map>
  6. #include<map>
  7. #include<stdio.h>
  8. #include<stdint.h>
  9. #include<string.h>
  10. using namespace std;
  11. #define MAX_NUM 105
  12. char gMap[MAX_NUM][MAX_NUM];
  13.  
  14. int dp[MAX_NUM][MAX_NUM][2];
  15. //dp[i][j][0] robot 从左侧进入(i, j)最少需要改变的次数
  16. //dp[i][j][1] robot 从上册进入(i, j)最少需要改变的次数
  17. #define INF 1 << 29
  18.  
  19. void debug(int m, int n){
  20. for (int i = 1; i <= m; i++){
  21. for (int j = 1; j <= n; j++){
  22. cout << "(" << i << ", " << j << ", 0) = " << dp[i][j][0] << ", ";
  23. cout << "(" << i << ", " << j << ", 1) = " << dp[i][j][1] << endl;
  24. }
  25. cout << endl;
  26. }
  27. }
  28. int min(int a, int b){
  29. return a < b ? a : b;
  30. }
  31. int main(){
  32. int m, n;
  33. scanf("%d %d", &m, &n);
  34. for (int i = 0; i < m; i++){
  35. getchar();
  36. for (int j = 0; j < n; j++){
  37. scanf("%c", &gMap[i][j]);
  38. dp[i + 1][j + 1][0] = INF;
  39. dp[i + 1][j + 1][1] = INF;
  40. }
  41. }
  42. int count = 0;
  43. for (int i = 1; i <= n; i++){
  44. if (gMap[0][i - 1] == 'b')
  45. count++;
  46. dp[1][i][0] = count;
  47. dp[1][i][1] = INF;
  48. }
  49. count = (gMap[0][1] != 'b');
  50. for (int i = 1; i <= m; i++){
  51. if (gMap[i - 1][0] == 'b')
  52. count++;
  53. dp[i][1][1] = count;
  54. dp[i][1][0] = INF;
  55. }
  56. dp[1][1][0] = 0;
  57.  
  58. for (int i = 2; i <= m; i++){
  59. for (int j = 2; j <= n; j++){
  60. int up_0 = dp[i - 1][j][0];
  61. int up_1 = dp[i - 1][j][1];
  62. int up_min = up_0 + !(j == n|| gMap[i - 2][j] == 'b');
  63. up_min = min(up_min, up_1);
  64. dp[i][j][1] = min(dp[i][j][1], up_min + (gMap[i - 1][j - 1] == 'b'));
  65.  
  66. int left_0 = dp[i][j - 1][0];
  67. int left_1 = dp[i][j - 1][1];
  68. int left_min = left_1 + !(i == m || gMap[i][j - 2] == 'b');
  69. left_min = min(left_min, left_0);
  70. dp[i][j][0] = min(dp[i][j][0], left_min + (gMap[i - 1][j - 1] == 'b'));
  71. }
  72. }
  73. int result = dp[m][n][0] < dp[m][n][1] ? dp[m][n][0] : dp[m][n][1];
  74. cout << result << endl;
  75. return 0;
  76. }

hiho_1290_demo_day的更多相关文章

随机推荐

  1. GOICE项目初探

    GOICE项目初探         在图像拼接方面,市面上能够找到的软件中,要数MS的ICE效果.鲁棒性最好,而且界面也很美观.应该说有很多值得学习的地方,虽然这个项目不开源,但是利用现有的资料,也可 ...

  2. PostgreSql安装

    官网:http://www.postgresql.org/download/linux/redhat/ 一.安装 由于我的机子是centos6.2,所以选择RedHat的. 按照官网所说的进行安装: ...

  3. Thread的六种状态

    线程共有6种状态:在某一时刻只能是这6种状态之一.这些状态由Thread.State这个枚举类型表示,并且可以通过getState()方法获得当前具体的状态类型. 包括(new,runnable,bl ...

  4. 2016年11月27日 星期日 --出埃及记 Exodus 20:18

    2016年11月27日 星期日 --出埃及记 Exodus 20:18 When the people saw the thunder and lightning and heard the trum ...

  5. 2016年7月1日 星期五 --出埃及记 Exodus 14:28

    2016年7月1日 星期五 --出埃及记 Exodus 14:28 The water flowed back and covered the chariots and horsemen--the e ...

  6. 【JSON】Jackson初学,及常用的例子

    现在很多公司的项目都基于SOA架构,系统间的调用有许多方式,其中一种常见的是用HTTP协议.以JSON格式返回结果. 这使得JSON的使用更加普遍.而市面上处理JSON的框架五花八门,常见的有JSON ...

  7. django下的ckeditor 5.0 文本编辑器上传功能。

    完整的后台界面怎么可以没有文本编辑器,但是django的admin界面很疑惑,没有自带文本编辑器,好在网上有不少成型的库可以用 我用的是ckeditor编辑器,安装和配置我引用别人的博客 这篇博客配置 ...

  8. Threads in Spring

    使用Spring时经常会问,我们定义的Bean应该是Singleton还是Prototype?多个客户端同时调用Dao层,需要考虑线程安全吗?通过阅读官方文档和Spring的源代码,这类问题的答案是: ...

  9. Flip Game poj1753

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 32961   Accepted: 14407 Description Fli ...

  10. EntityFramework 开始小试

    1 Install-Package EntityFramework 2 创建实体类 public class Blog { public int BlogId { get; set; } public ...