hiho 1290 —— Demo Day 【DP】

Demo Day

时间限制: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;
}

 

本项目是一个基于SSM(Spring+SpringMVC+MyBatis)框架和Vue.js前端技术的家教平台系统。该系统旨在为家教和学生提供一个便捷、高效的在线交流和预约平台,涵盖了从用户注册登录、个人信息管理、课程发布与搜索、预约与取消预约、评价反馈等一系列功能。 在后台管理方面,系统提供了管理员对用户信息、课程信息、预约记录等进行管理的功能,确保平台的正常运行和数据的准确性。通过Spring框架的依赖注入和AOP特性,实现了业务逻辑的清晰分离和高效处理;SpringMVC则负责处理前端请求和响应,提供友好的用户界面;MyBatis作为ORM框架,简化了数据库操作,提高了数据访问的效率和安全性。 前端部分采用Vue.js框架,结合Vue Router进行页面路由管理,Axios进行HTTP请求,实现了前后端分离的开发模式。Vue.js的组件化开发和响应式数据绑定特性,使得前端页面更加动态和交互性强,提升了用户体验。 数据库设计采用了MySQL,存储了用户信息、课程信息、预约记录等核心数据。通过合理的数据库表结构和索引设计,保证了系统的高效运行和数据的一致性。 该项目不仅适合计算机相关专业的毕设学生参考和学习,也适合Java学习者进行项目实战练习。通过对该项目的深入理解和二次开发,可以实现更多个性化功能,进一步提升技术水平和实践能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值