题目链接:https://www.rqnoj.cn/problem/342

题意:

  DD 有一个不太听话的机器人,这个机器人总是会有自己的想法,而不会完全遵守 DD 给它的指令。

  现在 DD 在试图命令机器人走迷宫。迷宫是一个 N*N 个格子组成的区域,格子自左上角到右下角从 (1,1) 到 (N,N) 编号。第 i 行、第 j 列的格子编号为 (i,j)。迷宫中的某些区域是障碍物,机器人不能移动到那里。

  DD 给了机器人 M 条指令,指令的类型包括“前进一步”“后退一步”“左转九十度”“右转九十度”。但问题是机器人并不能完全遵守这些指令,因为如果机器人完全遵守这些指令,它可能会走到障碍物的格子里或者走到迷宫外面去,那样就会有危险。机器人希望从这个指令序列里面去掉一些,然后执行剩下的指令时,可以保证整个过程中都不会有危险。

  机器人虽然不太听话,但它并不想惹恼了 DD,否则 DD 可能会把它拆掉的。所以机器人希望去掉的指令尽量少。

  迷宫的大小是 N*N,指令共有 M 条,机器人初始时的位置是 (X0,Y0)。机器人初始时面朝的方向是上方。

  那么,机器人最少需要去掉多少条指令才能保证不会有危险呢?

题解:

  表示状态:

    dp[i][x][y][d] = min num of deleted orders

    i:考虑到第i条指令

    x,y:当前位置

    d:当前方向

  找出答案:

    min legal dp[m][x][y][d]

  如何转移:

    now: dp[i][x][y][d]

    dp[i+1][x][y][d] = min dp[i][x][y][d] + 1 (不执行)

    dp[i+1][nx][ny][nd] = min dp[i][x][y][d] (执行)

    nx,ny,nd为执行第i条指令后的位置和方向。

  边界条件:

    dp[0][x0][y0][UP] = 0

    ohters = INF

    (UP为方向向上的编号)

  注:空间限制,要把第一维[MAX_M]变为[2]。

  小技巧:

    如果压维的时候前后数据间有影响,则可以开一个vis数组。

    更新dp[i&1][x][y][d]时,将vis[i&1][x][y][d] = i,意为当前dp的位置是在i的时候更新的。

    每次用到dp[i&1][x][y][d]时,判断一下相应的vis。

    如果vis[i&1][x][y][d] = i,则返回dp值,否则返回初始值INF(dp[i][x][y][d]这个状态还没被更新过)。

AC Code:

 // state expression:
// dp[i][x][y][d] = min num of deleted orders
// i: considering ith order
// x,y: present pos
// d: present direction
//
// find the answer:
// min legal dp[m][x][y][d]
//
// transferring:
// now: dp[i][x][y][d]
// dp[i+1][x][y][d] = min dp[i][x][y][d] + 1
// dp[i+1][nx][ny][nd] = min dp[i][x][y][d]
//
// bound:
// dp[0][x0][y0][UP] = 0
// ohters = INF
#include <iostream>
#include <stdio.h>
#include <string.h>
#define MAX_N 105
#define MAX_M 1005
#define MAX_D 5
#define INF 10000000 using namespace std; const int dx[]={-,,,};
const int dy[]={,,,-}; int n,m,x0,y0;
int ans;
int c[MAX_M];
int dp[][MAX_N][MAX_N][MAX_D];
int vis[][MAX_N][MAX_N][MAX_M];
char a[MAX_N][MAX_N]; void read()
{
cin>>n>>m>>x0>>y0;
for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
{
cin>>a[i][j];
}
}
string s;
for(int i=;i<m;i++)
{
cin>>s;
if(s=="FORWARD") c[i]=;
if(s=="BACK") c[i]=;
if(s=="LEFT") c[i]=;
if(s=="RIGHT") c[i]=;
}
} void cal_pos(int &x,int &y,int &d,int c)
{
if(c==)
{
x+=dx[d];
y+=dy[d];
return;
}
if(c==)
{
x-=dx[d];
y-=dy[d];
return;
}
if(c==)
{
d=(d+)%;
return;
}
if(c==)
{
d=(d+)%;
return;
}
} inline bool is_legal(int x,int y)
{
return x> && x<=n && y> && y<=n && a[x][y]!='*';
} void solve()
{
memset(dp,0x3f,sizeof(dp));
memset(vis,-,sizeof(vis));
dp[][x0][y0][]=;
vis[][x0][y0][]=;
for(int i=;i<m;i++)
{
for(int x=;x<=n;x++)
{
for(int y=;y<=n;y++)
{
if(a[x][y]!='*')
{
for(int d=;d<;d++)
{
if(vis[i&][x][y][d]==i)
{
int temp;
if(vis[(i+)&][x][y][d]!=i+) temp=INF;
else temp=dp[(i+)&][x][y][d];
dp[(i+)&][x][y][d]=min(temp,dp[i&][x][y][d]+);
vis[(i+)&][x][y][d]=i+;
int nx=x,ny=y,nd=d;
cal_pos(nx,ny,nd,c[i]);
if(is_legal(nx,ny))
{
if(vis[(i+)&][nx][ny][nd]!=i+) temp=INF;
else temp=dp[(i+)&][nx][ny][nd];
dp[(i+)&][nx][ny][nd]=min(temp,dp[i&][x][y][d]);
vis[(i+)&][nx][ny][nd]=i+;
}
}
}
}
}
}
}
ans=m;
for(int x=;x<=n;x++)
{
for(int y=;y<=n;y++)
{
if(a[x][y]!='*')
{
for(int d=;d<;d++)
{
if(vis[m&][x][y][d]==m)
{
ans=min(ans,dp[m&][x][y][d]);
}
}
}
}
}
} void print()
{
cout<<ans<<endl;
} int main()
{
read();
solve();
print();
}

RQNOJ 342 最不听话的机器人:网格dp的更多相关文章

  1. [Luogu P1006]传纸条 (网格DP)

    题面 传送门:https://www.luogu.org/problemnew/show/P1006 Solution 挺显然但需要一定理解的网络(应该是那么叫吧)DP 首先有一个显然但重要的结论要发 ...

  2. rqnoj-342-最不听话的机器人-dp

    dp[i][j][k][[l]: 执行第i步,执行到点(j,k),方向为l时,用的最大步数. 状态转移根据step[i]转移. #include<stdio.h> #include< ...

  3. RQNOJ 311 [NOIP2000]乘积最大:划分型dp

    题目链接:https://www.rqnoj.cn/problem/311 题意: 给你一个长度为n的数字,用t个乘号分开,问你分开后乘积最大为多少.(6<=n<=40,1<=k&l ...

  4. RQNOJ 622 最小重量机器设计问题:dp

    题目链接:https://www.rqnoj.cn/problem/622 题意: 一个机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得. w[i][j]是从供应商j处购得的部件i的重量, ...

  5. 1088. [SCOI2005]扫雷Mine【网格DP】

    Description 相信大家都玩过扫雷的游戏.那是在一个n*m的矩阵里面有一些雷,要你根据一些信息找出雷来.万圣节到了 ,“余”人国流行起了一种简单的扫雷游戏,这个游戏规则和扫雷一样,如果某个格子 ...

  6. 1084. [SCOI2005]最大子矩阵【网格DP】

    Description 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵 不能相互重叠. Input 第一行为n,m,k(1≤n≤100,1≤m≤ ...

  7. [Luogu P4147] 玉蟾宫 (网格DP)

    题面 传送门:https://www.luogu.org/problemnew/show/P4147 Solution 裸的求极大子矩阵 感谢wzj dalao的教学 首先,有一个很显然但很重要的结论 ...

  8. 【原创】POJ 1703 && RQNOJ 能量项链解题报告

    唉 不想说什么了 poj 1703,从看完题到写完第一个版本的代码,只有15分钟 然后一直从晚上八点WA到第二天早上 最后终于发现了BUG,题目要求的“Not sure yet.”,我打成了“No s ...

  9. 五大常见算法策略之——动态规划策略(Dynamic Programming)

    Dynamic Programming   Dynamic Programming是五大常用算法策略之一,简称DP,译作中文是"动态规划",可就是这个听起来高大上的翻译坑苦了无数人 ...

随机推荐

  1. 怎样通过Html网页调用本地安卓app

    怎样使用html网页和本地app进行传递数据呢?经过研究.发现还是有方法的,总结了一下,大致有一下几种方式 一.通过html页面打开Android本地的app 1.首先在编写一个简单的html页面 & ...

  2. C/C++中作用域详解(转)

    作用域规则告诉我们一个变量的有效范围,它在哪儿创建,在哪儿销毁(也就是说超出了作用域).变量的有效作用域从它的定义点开始,到和定义变量之前最邻近的开括号配对的第一个闭括号.也就是说,作用域由变量所在的 ...

  3. Nexus 5刷阿里云OS

    刷机有风险,刷机需慎重! 1. 下载 recovery 的img和 阿里云os. recovery 的img下载: https://kanbox.com/f/V00KA 阿里云OS3.0.3 : 2月 ...

  4. window.opener

    window.opener 实际上就是通过window.open打开的窗体的父窗体. 比如在父窗体parentForm里面 通过 window.open("subForm.html" ...

  5. VueJS组件之全局组件与局部组件

    全局组件 所有实例都能用全局组件. HTML <!DOCTYPE html> <html> <head> <meta charset="utf-8& ...

  6. Flex版的2048游戏

    近期2048游戏好像挺火.在公交,吃饭,甚至在路上走路都有人拿着手机在玩,之前我看同事玩,认为非常幼稚,移来移去太无聊了吧 到后面自己也下了.发现确实挺无聊的,也就是在无聊的时候打发无聊的时间,后来就 ...

  7. ck-reset css(2016/5/13)

    /**rest by 2016/05/04 */ * {box-sizing: border-box;} *:before,*:after {box-sizing: border-box;} body ...

  8. js 中的 prototype 和 constructor

    var a=function(){ this.msg="aa"; } a.prototype.say=function(){ alert('this is say');} 1.只有 ...

  9. 【Servlet与JSP】请求转发与重定向

    假设一个登录系统,要求用户输入用户名和密码: 用户在上面表单当中输入了信息之后,点击登录按钮(type="submit")将表单作为请求参数进行提交. 这一提交就有两种形式:get ...

  10. python学习(八)阶段性总结

    这里学习了python的一点点基础然后来总结一下 python是一个强类型的语言 数字: 数字的类型大概有:整数.浮点数.复数.固定精度的十进制数.带分子和分母的有理数 数字与字符串之间不能直接相加, ...