hdu1428 记忆化搜索(BFS预处理最短路径和+DP+DFS)
题意:有一块 n * n 大小的方形区域,要从左上角 (1,1)走到右下角(n,n),每个格子都有通过所需的时间,并且每次所走的下一格到终点的最短时间必须比当前格子走到重点的最短时间短,问一共有多少种走法。
这道题还是很明显的 DP 的,而且鉴于走到相邻格点可以上下左右走,所以我很快就锁定了记忆化搜索这种 DP 方式,但是事实上我的思路大方向的确没有错误,但是我仍然没有很好地挖掘题目的信息。我的想法是,某点到结尾的最短距离我可以转化成到起始点的最短距离,这样我就能从开头的点开始遍历,并且在遍历的时候,如果前后左右有点可以被当前的点优化(即从当前点走到下个点所花总时间比下个点上原本的最短时间还要短,那么我就用当前点优化下一个点,并继续从下一个点 DFS ),我觉得我想的挺对的,而且事实上我认为我的做法本身是可以解这题的,但是仍然会超时。
恩,其实到这里,问题都很明显了,记忆化搜索原本就是很有效地解决超时的一种手段,我之所以超时是因为我用的根本就不是记忆化搜索,而是很普通的 DPS ,DP 数组也只是为了便于传递状态而不是用于记忆,归根结底是我对记忆化搜索的认识还不够,我并没有掌握它,更没有理解记忆究竟是怎么样的,这之前写的两道记忆化搜索的题目其实都有一个共同点,用 DP 数组记录最优解,当再次遍历到这个点的时候就能够直接输出这个 DP 值,而在图中上下左右走根本只是一个题目的出现方式而已。
对题目的理解不到位也是很严重的一个问题,在本题中,已经很清楚地说明了下一个格子到终点的最短时间要比这一个格子到终点的最短时间短,很明显,我只要现处理出每一个点到终点的最短时间,这道题就和之前做的 hdu 1078 几乎一样了。
预处理出最短路径的方法我用的是 BFS ,从终点开始,每当周围有某个点可以用当前点优化,就将它优化后放回队列继续执行操作,当处理出最短路径之后,再用记忆化搜索的方式对整个图 DFS 一遍,用 DP 数组记录每个点到终点共有多少条路可以走,这样就可以得到答案了。
首先是我 TLE 的纯 DFS 代码:
#include<stdio.h>
#include<string.h>
#define ll long long int n;
ll dp[][],m[][],t[][];
int xx[]={,-,,};
int yy[]={,,,-}; void dfs(int x,int y){
int i,j;
for(i=;i<;i++){
int dx=x+xx[i],dy=y+yy[i];
if(dx>=&&dx<=n&&dy>=&&dy<=n){
if(dp[dx][dy]==-||(dp[dx][dy]>dp[x][y]+t[dx][dy])){
dp[dx][dy]=dp[x][y]+t[dx][dy];
m[dx][dy]=m[x][y];
dfs(dx,dy);
}
else if(dp[dx][dy]==dp[x][y]+t[dx][dy]){
m[dx][dy]=;
for(j=;j<;j++){
int ddx=dx+xx[j],ddy=dy+yy[j];
if(ddx>=&&ddx<=n&&ddy>=&&ddy<=n&&(dp[ddx][ddy]+t[dx][dy]==dp[dx][dy])){
m[dx][dy]+=m[ddx][ddy];
}
} dfs(dx,dy);
}
}
}
} int main(){
while(scanf("%d",&n)!=EOF){
int i,j;
memset(dp,-,sizeof(dp));
memset(m,,sizeof(m));
for(i=;i<=n;i++){
for(j=;j<=n;j++){
scanf("%I64d",&t[i][j]);
}
}
dp[][]=t[][];
m[][]=;
dfs(,);/*
printf("dp:\n");
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
printf("%d ",dp[i][j]);
}
printf("\n");
}
printf("m:\n");
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
printf("%d ",m[i][j]);
}
printf("\n");
}*/
printf("%I64d\n",m[n][n]);
}
return ;
}
然后是我用 BFS 处理最短路径再记忆化搜索的代码:
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define ll long long int n,c; struct point{
int x,y;
}; ll m[][],dp[][];
int t[][];
int xx[]={,-,,};
int yy[]={,,,-};
bool in[][]; void bfs(){
int i;
point p,p1;
p1.x=n;
p1.y=n;
in[p1.x][p1.y]=;
queue<point>q;
q.push(p1);
m[n][n]=t[n][n];
while(!q.empty()){
p=q.front();
q.pop();
in[p.x][p.y]=;
for(i=;i<;i++){
p1.x=p.x+xx[i];
p1.y=p.y+yy[i];
if(p1.x>=&&p1.x<=n&&p1.y>=&&p1.y<=n&&(m[p1.x][p1.y]==-||m[p1.x][p1.y]>m[p.x][p.y]+t[p1.x][p1.y])){
m[p1.x][p1.y]=m[p.x][p.y]+t[p1.x][p1.y];
if(!in[p1.x][p1.y]){
q.push(p1);
in[p1.x][p1.y]=;
}
}
}
}
} long long dfs(int x,int y){
if(x==n&&y==n)return ;
if(dp[x][y])return dp[x][y];
int i;
for(i=;i<;i++){
int dx=x+xx[i],dy=y+yy[i];
if(dx>=&&dx<=n&&dy>=&&dy<=n&&m[dx][dy]<m[x][y]){
dp[x][y]+=dfs(dx,dy);
}
}
return dp[x][y];
} int main(){
while(scanf("%d",&n)!=EOF){
int i,j;
memset(m,-,sizeof(m));
memset(dp,,sizeof(dp));
memset(in,,sizeof(in));
for(i=;i<=n;i++){
for(j=;j<=n;j++){
scanf("%d",&t[i][j]);
}
}
bfs();
printf("%I64d\n",dfs(,));
}
return ;
}
hdu1428 记忆化搜索(BFS预处理最短路径和+DP+DFS)的更多相关文章
- hdu1428(记忆化搜索)
题意:“他考虑从A区域到B区域仅当存在一条从B到机房的路线比任何一条从A到机房的路线更近(否则可能永远都到不了机房了…”这句话一定要理解清楚.就是说,对于当前位置,如果下一个状态与终点的最短距离大于或 ...
- luogu1514 [NOIp2010]引水入城 (bfs+记忆化搜索)
我们先bfs一下看看是否能到最底下的所有点 如果不能的话,直接把不能到的那几个数一数就行了 如果能的话: 可以发现(并不可以)某格能到达的最底下的格子一定是一个连续的区间 (因为如果不连续的话,我们先 ...
- 【bzoj1415】[Noi2005]聪聪和可可 期望记忆化搜索
题目描述 输入 数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数. 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号. 接下来E行 ...
- 专题1:记忆化搜索/DAG问题/基础动态规划
A OpenJ_Bailian 1088 滑雪 B OpenJ_Bailian 1579 Function Run Fun C HDU 1078 FatMouse and Chee ...
- 二进制数(dp,记忆化搜索)
二进制数(dp,记忆化搜索) 给定k个<=1e6的正整数x(k不大于10),问最小的,能被x整除且只由01组成的数. 首先,dp很好写.用\(f[i][j]\)表示i位01串,模ki的值是j的数 ...
- hdu1978How many ways (记忆化搜索+DFS)
Problem Description 这是一个简单的生存游戏,你控制一个机器人从一个棋盘的起始点(1,1)走到棋盘的终点(n,m).游戏的规则描述如下: 1.机器人一开始在棋盘的起始点并有起始点所标 ...
- UVA 103 Stacking Boxes (dp + DAG上的最长路径 + 记忆化搜索)
Stacking Boxes Background Some concepts in Mathematics and Computer Science are simple in one or t ...
- uva 10581 - Partitioning for fun and profit(记忆化搜索+数论)
题目链接:uva 10581 - Partitioning for fun and profit 题目大意:给定m,n,k,将m分解成n份,然后依照每份的个数排定字典序,而且划分时要求ai−1≤ai, ...
- hdoj1078(介绍记忆化搜索及其模板)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1078 思路: 这是一道典型的记忆化搜索模板题. 先介绍记忆化搜索,本质是搜索+DP. 一般说来,动态规 ...
随机推荐
- Eclipse 打包Web项目
使用插件fatjar Fat jar插件 http://kurucz-grafika.de/fatjar eclipse菜单栏 help->install new software...-> ...
- 20170813xlVBA跨表筛选数据
一.数组方案 Sub CustomFilter() Dim Rng As Range, Arr As Variant Dim EndRow As Long, EndCol As Long Dim i ...
- 『Json』常用方法记录
json模块可以把字典结构改写为string然后保存,并可以反向读取字典 pickle模块则可以持久化任意数据结构 但是即使同样是字典数据结构,两个包也是有差别的, json字典value不支持其他对 ...
- 3-1 LVS-NAT集群
---- (整理)By 小甘丶 什么是集群: 集群是一组相互独立的.通过高速网络互联的计算机,它们构成了一个组,并以单一系统的模式加以管理.(Cluster就是一组计算机,它们作为一个整体向用户提供一 ...
- python-day4笔记
1.文件后缀名对python运行没关系 2.Python解释器执行python程序的过程:python3 C:\test.py 1)启动python解释器(内存中) 2)将C:\test.py内容从硬 ...
- 第5章——使用 Razor(MVC框架视图引擎)
Razor 是MVC框架视图引擎的名称. 本章提供 Razor 语法的快速教程,以使你能够识别 Razor 表达式. 本章不打算提供 Razor 的完整参考,而将其视为一个语法速成教程.在本书的后续内 ...
- 使用UTL_SMTP发送中文邮件及使用UTL_TCP从附件服务器获取中文附件
先上最重要的干货 发送邮件正文及主题的时候一定要使用convert重新编码 主题: utl_smtp.write_raw_data(l_mail_conn, utl_raw.cast_to_raw(c ...
- win7 安装express
1.以管理员身份打开cmd(避免出错) npm install -g express-generator@4 Start the server: npm start 链接,github官网说明 htt ...
- 微信小程序--登录流程梳理
前言 微信小程序凡是需要记录用户信息都需要登录,但是也有几种不同的登录方式,但是在小程序部分的登录流程是一样的.之前就朦朦胧胧地用之前项目的逻辑改改直接用了,这个新项目要用就又结合官方文档重新梳理了下 ...
- 用Maven创建第一个web项目
http://www.cnblogs.com/leiOOlei/p/3361633.html 一.创建项目 1.Eclipse中用Maven创建项目 上图中Next 2.继续Next 3.选maven ...