就我的理解来说这个题,本质上是一个DP题,不应该说是搜索,因为我的做法是把表格中所有的数据都找到,使用队列暴力来遍历出所有状态,因为题目中的数据范围小,所有耗时也小。

  首先分析箱子是一个被动物体,人是主动物体,箱子的移动取决于人的移动,所以在bfs中只需要让人去移动,进而带动箱子就可以了。我们使用dp[x1][y1][x2][y2]来记录状态,分别代表人和箱子的位置。在队列实现DP的过程中,我们必须要把当前所在的情况标记为未走过,这个很重要。有人可能会质疑,这样可能导致无限的入队列,导致死循环,所以需要一个技巧,首先新的状态是否更新跟这个状态是否被标记无关,所以能否让这个点入队列,需要首先满足状态值得更新的条件,所以我们不可能去走无意义的回头路,不可能会产生走过来走过去,从而导致死循环的情况。然后就要满足这个点未被标记的情况,才能入队列,标记这个点。

  当然有人也会问,只要把状态更新了就可以了,干嘛非要入队列呢?如果不仅队列,更新的仅仅是这个状态,其他的状态无法经过他转移,无法获得最优子结构,就不符合DP的思想,就是错误的了。(当然这个地方可能也仅仅是我不懂,但是这个标记方法还是很重要的),我给出一个例子吧。

0 0 0 0 0 0

0 0 1 1 1 0

0 0 1 4 0 0

0 0 1 2 1 0

0 0 0 0 3 0

0 0 0 0 1 0

0 0 0 0 0 0

我相信你很快就能找出两种方法来,往上走耗费的步数多,在bfs过程中也是后来达到的点,所以bfs第一次到两个加粗的0的时候,耗费步数少,但是推的次数多,而题目中要求最小的推数,与走的步数无关,所以这点必须更新并且入队列更新其他的点,如果我们没有把以前的标记消除,导致入队列失败,更新失败,答案出错。

最后一句话总结,在队列实现dp的过程中,一定记着把以前的标记消除,让新的点入队列,更新其他的状态,才能得到最后的最优解。

代码如下:

#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;
#define maxn 10
#define INF 999999999
int dp[maxn][maxn][maxn][maxn],n,m,maps[maxn][maxn];
int go[][] = {{,},{-,},{,},{,-}};
int vis[maxn][maxn][maxn][maxn],endx,endy;
struct Node
{
int x1,y1,x2,y2;
Node () {};
Node(int xx1,int yy1,int xx2,int yy2)
{
x1 = xx1;
y1 = yy1;
x2 = xx2;
y2 = yy2;
}
};
void mark(Node a)
{
vis[a.x1][a.y1][a.x2][a.y2] = ;
}
bool ok(int x,int y)
{
return (x>=&&x<n && y>=&&y<m && maps[x][y]!=);
}
int bfs(Node start)
{
queue<Node> que;
memset(vis,,sizeof(vis));
while(!que.empty()) que.pop();
que.push(start);
dp[start.x1][start.y1][start.x2][start.y2] = ;
//mark(start);
while(!que.empty())
{
Node now = que.front();
que.pop();
int x1 = now.x1,y1 = now.y1;
int x2 = now.x2,y2 = now.y2;
vis[x1][y1][x2][y2] = ;///进入队列,消除标记
int xx1,xx2,yy1,yy2;
for(int i = ; i < ; i++)
{
xx1 = x1 + go[i][];
yy1 = y1 + go[i][];
if(ok(xx1,yy1))
{
if(xx1 == x2 && yy1 == y2)
{
xx2 = x2 + go[i][];
yy2 = y2 + go[i][];
if(ok(xx2,yy2))
{
if(dp[xx1][yy1][xx2][yy2]==- || dp[xx1][yy1][xx2][yy2]>dp[x1][y1][x2][y2]+)///第一层检验
{
dp[xx1][yy1][xx2][yy2] = dp[x1][y1][x2][y2]+;///更新当前点状态
if(!vis[xx1][yy1][xx2][yy2])
{
Node nxt(xx1,yy1,xx2,yy2);
mark(nxt);///进入队列,更新其他点
que.push(nxt);
}
} }
}
else
{
if(dp[xx1][yy1][x2][y2]== - || dp[xx1][yy1][x2][y2]>dp[x1][y1][x2][y2])
{
dp[xx1][yy1][x2][y2] = dp[x1][y1][x2][y2];
if(!vis[xx1][yy1][x2][y2])
{
Node nxt(xx1,yy1,x2,y2);
mark(nxt);
que.push(nxt);
}
}
}
}
}
}
int ans = INF;
for(int i = ; i < n; i++)
{
for(int j = ; j < m; j++)
{
//printf("dp[%d][%d] = %d\n",i,j,dp[i][j][endx][endy]);
if(dp[i][j][endx][endy] != -)
ans = min(ans,dp[i][j][endx][endy]);
}
}
if(ans != INF) return ans;
return -;
}
int main()
{
while(~scanf("%d%d",&m,&n))
{
if(n+m == ) break;
Node start;
for(int i = ; i < n; i++)
{
for(int j = ; j < m; j++)
{
scanf("%d",&maps[i][j]);
if(maps[i][j] == )
{
start.x2 = i;
start.y2 = j;
}
if(maps[i][j] == )
{
start.x1 = i;
start.y1 = j;
}
if(maps[i][j] == )
{
endx = i;
endy = j;
}
}
}
memset(dp,-,sizeof(dp));
int ans = bfs(start);
printf("%d\n",ans);
}
return ;
}

UVALive 2147 Push!!(队列实现DP)的更多相关文章

  1. hdu3401:单调队列优化dp

    第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...

  2. SCOI 股票交易 单调队列优化dp

    这道题 我很蒙.....首先依照搞单调队列优化dp的一般思路 先写出状态转移方程 在想法子去优化 这个题目中说道w就是这一天要是进行操作就是从前w-1天转移而来因为之前的w天不允许有操作!就是与这些天 ...

  3. 「学习笔记」单调队列优化dp

    目录 算法 例题 最大子段和 题意 思路 代码 修剪草坪 题意 思路 代码 瑰丽华尔兹 题意 思路 代码 股票交易 题意 思路 代码 算法 使用单调队列优化dp 废话 对与一些dp的转移方程,我们可以 ...

  4. 【转】单调队列优化DP

    转自 : http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列是一种严格单调的队列,可以单调递增,也可以单调递减.队 ...

  5. 单调队列优化DP,多重背包

    单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...

  6. bzoj1855: [Scoi2010]股票交易--单调队列优化DP

    单调队列优化DP的模板题 不难列出DP方程: 对于买入的情况 由于dp[i][j]=max{dp[i-w-1][k]+k*Ap[i]-j*Ap[i]} AP[i]*j是固定的,在队列中维护dp[i-w ...

  7. 【HDU 3401 Trade】 单调队列优化dp

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3401 题目大意:现在要你去炒股,给你每天的开盘价值,每股买入价值为ap,卖出价值为bp,每天最多买as ...

  8. Parade(单调队列优化dp)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others)    ...

  9. BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP

    BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...

随机推荐

  1. GetLastError() 返回值含义

    [0]-操作成功完成.[1]-功能错误.[2]-系统找不到指定的文件.[3]-系统找不到指定的路径.[4]-系统无法打开文件.[5]-拒绝访问.[6]-句柄无效.[7]-存储控制块被损坏.[8]-存储 ...

  2. ejabberd组成模块

    转自:http://blog.sina.com.cn/u/1776260990 mod_adhoc 特定命令 (XEP-0050) mod_announce 管理公告推荐 mod_adhoc mod_ ...

  3. iOS动画编程

    IOS中的动画总结来说有五种:UIView<block>,CAAnimation<CABasicAnimation,CATransition,CAKeyframeAnimation& ...

  4. Centos7 设置DNS 服务器

    在CentOS 7下,手工设置 /etc/resolv.conf 里的DNS,过了一会,发现被系统重新覆盖或者清除了.和CentOS 6下的设置DNS方法不同,有几种方式: 1.使用全新的命令行工具 ...

  5. xtrabackup 2.0.8备份mysql5.1.65报错

    sh : xtrabackup not found innobackupex: fatal error: no 'mysqld' group in MySQL options fix: add inn ...

  6. C Runtime Library来历, API, MFC, ATL关系

    首先说明,我google了半天,想找到英文的关于这个资料,但是实在找不到,只好转载国人的讨论. CRT原先是指Microsoft开发的C Runtime Library,用于操作系统的开发及运行.后来 ...

  7. ubuntu 下配置vim for python

    apt-get install vim-gnome apt-get install ctags apt-get install vim-scripts vim-addons install tagli ...

  8. jQuery(1)——了解jQuery

    jQuery 终于开始了jQuery的学习了,好开心,虽然感觉JavaScript并没有学好,尴尬.木事,咋们慢慢来.fighting [jQuery简介] jQuery是继Prototype之后又一 ...

  9. 小Q系列故事——电梯里的爱情

    小Q系列故事——电梯里的爱情 Time Limit : 300/100ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other) Total ...

  10. php - preg_match

    任务:匹配一个函数名或者变量名,如果碰到alpha,numeric,_以外的全部不允许通过. 实验1: <?php //第一个字符不符合就直接退出正则匹配 $str = '%abcscript% ...