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. 一般说来,动态规 ...
随机推荐
- WCF配置后支持通过URL进行http方式调用
最近遇到一个小型项目,主要就是通过手机写入NFC信息,思考许久后决定就写一个简单的CS程序来搞定这个问题,可是当涉及到手机和PC通信的时候首先考虑到的就是IIS,同时因为数据库是SQLite,思前想后 ...
- ural Ambitious Experiment 树状数组
During several decades, scientists from planet Nibiru are working to create an engine that would all ...
- hdu2087kmp
一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案.对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢? Input输入中含有一些数据,分别是成对出现的花布条和 ...
- thinkphp if标签
1.thinkphp框架中的if标签,用于html页面中.在html中编写php代码 1).从控制器中得到数据在循环中if else 判断:<volist name="system_r ...
- hdu-2509-反nim博弈
Be the Winner Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot ...
- Leetcode 113
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode ...
- python 抓取搜狗微信出现的问题,求大神解决
爬取到的data不是想要获取文章页面的源码,而是跳转到验证码的页面的源码.我网上查了一下是由于访问过于频繁导致的,我也加了time.sleep和改了请求头但还是显示不了,求大神支招,除了识别验证码的方 ...
- mysql判断表记录是否存在,不存在则插入新纪录
开始以为和SQL Server一样,使用not exists进行判断,结果不行: ) INSERT INTO vrv_paw_template(templateName,templateFileNam ...
- vs2012修改代码编辑区域的背景色
- Syntax error: Bad for loop variable解决办法
从 ubuntu 6.10 开始,ubuntu 就将先前默认的bash shell 更换成了dash shell:其表现为 /bin/sh 链接倒了/bin/dash而不是传统的/bin/bash. ...