hiho 1290 —— Demo Day 【DP】

时间限制:10000ms  单点时限:1000ms  内存限制:256MB

描述

You work as an intern at a robotics startup. Today is your company's demo day. During the demo your company's robot will be put in a maze and without any information about the maze, it should be able to find a way out.

The maze consists of N * M grids. Each grid is either empty(represented by '.') or blocked by an obstacle(represented by 'b'). The robot will be release at the top left corner and the exit is at the bottom right corner.

Unfortunately some sensors on the robot go crazy just before the demo starts. As a result, the robot can only repeats two operations alternatively: keep moving to the right until it can't and keep moving to the bottom until it can't. At the beginning, the robot keeps moving to the right.

rrrrbb..            
...r....     ====> The robot route with broken sensors is marked by 'r'. 
...rrb..
...bb...

While the FTEs(full-time employees) are busy working on the sensors, you try to save the demo day by rearranging the maze in such a way that even with the broken sensors the robot can reach the exit successfully. You can change a grid from empty to blocked and vice versa. So as not to arouse suspision, you want to change as few grids as possible. What is the mininum number?

输入

Line 1: N, M.

Line 2-N+1: the N * M maze.

 

For 20% of the data, N * M <= 16.

For 50% of the data, 1 <= N, M <= 8.

For 100% of the data, 1<= N, M <= 100.

输出

The minimum number of grids to be changed.

样例输入
4 8
....bb..
........
.....b..
...bb...
样例输出
1

分析:dp[i][j] 定义为:当机器人从(0,0)出发,到达(i, j)时,所需要的最少操作数。

然后,可以通过枚举转折点(方向改变的点),来进行状态转移。

比如说,对于dp[i][j],只有两种情况:

  1. 机器人从坐标(i, [0,1,...,m-1])向右走到(i, j)
  2. 机器人从坐标([0,1,...,n-1],  j)向下走到(i, j)

我们其实只用取两种情况的最小值即可。

现在考虑第1种情况:

  坐标(i, [0,1,...,m-1])中,最关键的点其实是转折点,即机器人向下走到这个点(i, k),然后转向,向右走到了(i, j)

  dp[i][j] = min(dp[i][j], dp[i][k] + {转向需要改变方格类型吗?1:0} + {区间map[i][k+1, j]这一段有多少障碍} )

第二种情况类似于第一种。

 

自顶向下版本,数据范围严苛时,会有栈溢出的危险。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#define INF 0x3f3f3f3f
using namespace std;

char map[105][105];
int dp[105][105];
int n, m;

int f(int a, int b)
{
    if(dp[a][b] != -1)    return dp[a][b];
    
    int cur = INF, tot=map[a][b]=='b';
    
    for(int i=b-1; i>=0; i--) {
        cur = min(cur, f(a, i) + tot + (a<n-1 && map[a+1][i]!='b'));
        if(map[a][i]=='b') {
            tot++;
        }
    }
    tot=map[a][b]=='b';
    for(int i=a-1; i>=0; i--) {
        cur = min(cur, f(i, b) + tot + (b<m-1 && map[i][b+1]!='b'));
        if(map[i][b]=='b') {
            tot++;
        }
    }
    return dp[a][b] = cur;
}

int main ()
{
    scanf("%d%d", &n, &m);
    
    for(int i=0; i<n; i++) {
        scanf("%s", map[i]);
    }
    
    memset(dp, -1, sizeof(dp));
    
    int tot=0;
    for(int j=0; j<m; j++) {
        if(map[0][j]=='b')    tot++;
        dp[0][j] = tot;
    }
    
    printf("%d\n", f(n-1, m-1));
        
//    for(int i=0; i<n; i++) {
//        for(int j=0; j<m; j++) {
//            printf("%d ", f(i,j));
//        }
//        printf("\n");
//    }
    return 0;
}

 自底向上版本:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#define INF 0x3f3f3f3f
using namespace std;

char map[105][105];
int dp[105][105];
int n, m;

int main ()
{
    scanf("%d%d", &n, &m);
    
    for(int i=0; i<n; i++) {
        scanf("%s", map[i]);
    }
    
    memset(dp, -1, sizeof(dp));
    
    int tot=0;
    for(int j=0; j<m; j++) {
        if(map[0][j]=='b')    tot++;
        dp[0][j] = tot;
    }
    
    int cnt, temp;
    for(int i=1; i<n; i++) {
        for(int j=0; j<m; j++) {
            cnt = map[i][j]=='b';
            temp = INF;
            for(int k=j-1; k>=0; k--) {
                temp = min(temp, dp[i][k]+cnt+(i<n-1&&map[i+1][k]!='b'));
                cnt += map[i][k]=='b';
            }
            cnt = map[i][j]=='b';
            for(int k=i-1; k>=0; k--) {
                temp = min(temp, dp[k][j]+cnt+(j<m-1&&map[k][j+1]!='b'));
                cnt += map[k][j]=='b';
            }
            dp[i][j] = temp;
        }
    }
    printf("%d\n", dp[n-1][m-1]);
        
//    for(int i=0; i<n; i++) {
//        for(int j=0; j<m; j++) {
//            printf("%d ", dp[i][j]);
//        }
//        printf("\n");
//    }
    return 0;
}

 

posted on 2016-04-26 13:23  SuperChan  阅读(219)  评论(0编辑  收藏  举报

导航