Oj 24260: Lilypad Pond (神奇广搜题,状态搜索)
题目
为了让奶牛们娱乐和锻炼,约翰建造了一个美丽的池塘。这个池塘是矩形的,可以分成M×N个方格。一些格子是坚固得令人惊讶的莲花,还有一些是岩石,其余的只是美丽,纯净,湛蓝的水。
贝西正在练习芭蕾舞,她站在一朵莲花上,想跳到另一朵莲花上去,她只能从一朵莲花跳到另一朵莲花上,既不能跳到水里,也不能跳到岩石上。
贝西的舞步很像象棋中的马步:每次跳跃可以横移2格,纵移1格,或纵移1格,横移2格,最多有八个方向可供移动选择。
约翰一直在观察贝西的芭蕾练习,发现她有时不能跳到终点,因为中间缺了一些必要的莲花。约翰可以多种一些莲花来帮助贝西到达终点。不过要。注意有石头的格子是不能种莲花的
请帮助约翰求出至少要添加几朵莲花才能让贝西跳到终点,记这个数字为L,再求出添加大号朵莲花后贝西跳到终点的最少步 ,记这个数字为J.最后求出添加大号朵莲花后跳到终点的步数为Ĵ的路线有多少条,记这个数字为W.
- 输入格式
第一行:两个用空格分开的整数:M和N,1≤M,N≤30
第二行到M + 1行:第i +1行有N个用空格分开的整数,描述了池塘第i行的状态:0为水,1为莲花,2为岩石,3为起点,4为终点。
- 输出格式
第一行:一个整数:L,即需要添加的最少莲花数目,如果无解输出-1
第二行:一个整数:J-,如果第一行是-1,输出不需要行这
第三行:一个整数:W,如果第一行是-1,不需要输出这行
- 示例输入
4 8
0 0 0 1 0 0 0 0
0 0 0 0 0 2 0 1
0 0 0 0 0 4 0 0
3 0 0 0 0 0 1 0
- 示例输出
2
6
2
分析:一开始很容易想到使用深收,但是超时了,不过还是提供下代码;然后我们可以想到用广搜来解决问题。
用f[ i ][ j ]记录走到 i , j 的状态怎么样;
用结构体保存当前到(x,y)的最小增加的荷花的数量、最小步数、在当前荷花数、步数的条件下的方案数(用long long)
那么每次广搜的时候更新只考虑三种情况:
1、当前点的荷花数比目标荷花数更优,那么直接照搬过来
2、当前点的荷花数和目标一样优,这样又要分三小点:
①当前点的步数比目标优,那么只要更新步数和方案数就好了
②当前点的步数和目标一样优,那么方案数加上去,其他原封不动
③当前点的步数不如目标优,那么直接不管它就好了
3、当前点的荷花数不如目标荷花数优,不管它
AC代码:
#include<stdio.h>
#include<queue>
#include<string.h>
#define INF 0x3f3f3f3f
using namespace std;
struct nod
{
int add;///增加的荷花数
int step;///步数
long long num;///多少的次数
}f[][];
struct noo
{
int x;
int y;
}q[];
bool book[][];///标记
int e[][];///建图
///方向数组 int ex,sx,ey,sy,n,m;
void DFS()///实际上是DFS+SPFA;
{
int net[][]={{-,},{-,},{,},{,},{,-},{,-},{-,-},{-,-}};
int head,tail,tx,ty,t;
head=tail=;
q[tail].x=sx;q[tail].y=sy;///起点进队列
tail++;
book[sx][sy]=;///标记
while(head<tail)///当队列不为空
{
int nx=q[head].x,ny=q[head].y;
head++;///出队
for(int k=;k<;k++)///枚举8个方向目标点
{
tx=net[k][]+nx;
ty=net[k][]+ny;
if(tx<||ty<||tx>n||ty>m||e[tx][ty]==)
continue;///越界与是障碍
///判断目标点是否为0或1
if(e[tx][ty]==)
t=;
else
t=;
///iF当前点的加花情况比目标点的好
///目标点照搬当前点
if(f[tx][ty].add>f[nx][ny].add+t)
{
f[tx][ty].add=f[nx][ny].add+t; f[tx][ty].step=f[nx][ny].step+; f[tx][ty].num=f[nx][ny].num;
if(book[tx][ty]==)
{
book[tx][ty]=;
q[tail].x=tx;
q[tail].y=ty;
tail++;
} }
///if当前点的荷花与目标点的荷花数一样
else if(f[tx][ty].add==f[nx][ny].add+t)
{
///当前点的步数比目标点的更少
///只要更新步数和方案数就好了
if(f[tx][ty].step>f[nx][ny].step+)
{
f[tx][ty].step=f[nx][ny].step+;
f[tx][ty].num=f[nx][ny].num;
if(book[tx][ty]==)
{
book[tx][ty]=;
q[tail].x=tx;
q[tail].y=ty;
tail++;
}
} ///当前点的步数和目标一样优,那么方案数加上去,其他原封不动
else if(f[tx][ty].step==f[nx][ny].step+)
{
f[tx][ty].num+=f[nx][ny].num;
if(book[tx][ty]==)
{
book[tx][ty]=;
q[tail].x=tx;
q[tail].y=ty;
tail++;
}
} }
}
book[nx][ny]=;///取消标记,因为我还可以走重复的点啊
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(book,,sizeof(book));
memset(f,,sizeof(f));
memset(q,,sizeof(q));
///建图与初始化
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
scanf("%d",&e[i][j]);
f[i][j].add=INF;
f[i][j].step=INF;
if(e[i][j]==)
{
sx=i;
sy=j;
f[i][j].add=;
f[i][j].step=;
f[i][j].num=;
}
if(e[i][j]==)
{
ex=i;
ey=j;
}
}
DFS();
if(f[ex][ey].add!=INF)
printf("%d\n%d\n%lld\n",f[ex][ey].add,f[ex][ey].step,f[ex][ey].num);
else
printf("-1\n");
}
}
深收超时的代码,虽然超时不过值得学习;
#include <queue>
#include <stack>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int movex[]={,,,,-,-,-,-},movey[]={-,,-,,-,,-,};
int L=<<,J=<<,W,n,m,sx,sy,ex,ey,A[][],P[][];
void Dfs(int x,int y,int cnt,int tmp){
if (cnt>L) return;
if (cnt==L && tmp>J) return;
if (x==ex && y==ey){
if (cnt==L){
if (tmp==J) W++;
else if (tmp<J) J=tmp,W=;
}
else if (cnt<L) L=cnt,J=tmp,W=;
return;
}
for (int i=;i<;i++){
int xx=x+movex[i],yy=y+movey[i];
if (xx>= && xx<=n && yy>= && yy<=m && A[xx][yy]!= && P[xx][yy]==){
if (A[xx][yy]==){
P[xx][yy]=;
Dfs(xx,yy,cnt,tmp+);
P[xx][yy]=;
}
if (A[xx][yy]==){
P[xx][yy]=;
Dfs(xx,yy,cnt+,tmp+);
P[xx][yy]=;
}
}
}
}
int main(){
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++){
for (int j=;j<=m;j++){
scanf("%d",&A[i][j]);
if (A[i][j]==) sx=i,sy=j,A[i][j]=;
if (A[i][j]==) ex=i,ey=j,A[i][j]=;
}
}
P[sx][sy]=;
Dfs(sx,sy,,);
if (L==<<) printf("-1");
else printf("%d\n%d\n%d",L,J,W);
fclose(stdin); fclose(stdout);
return ;
}
题后感想:
打的时候有了灵感应该抓住往下想。某种意义上深收与广搜相同,可以用做深搜的思想来做出广搜
Oj 24260: Lilypad Pond (神奇广搜题,状态搜索)的更多相关文章
- hdu 2612:Find a way(经典BFS广搜题)
Find a way Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- HDU 1495 非常可乐 (只是转了个弯的广搜题)
N - 非常可乐 =========================================================================================== ...
- 一道简单的广搜题:Knight Moves
这本来是要用双向宽度搜索的,但是我用简单的广搜也成功了,L<=300,也不会超时?? 另外一个问题就是,我本来想用原来的代码交,结果80分??将边界条件从小于L改成小于等于L,就对了.我可能不会 ...
- 魔板 Magic Squares(广搜,状态转化)
题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题目描述 我们知道魔板的每一个方格都有一种颜色.这8种颜 ...
- hdu 1180 诡异的楼梯(广搜,简单)
题目 挺简单的一道广搜题,只要用判断时间是偶数还是奇数就可以判断楼梯的方位,但是我这傻逼居然写了那么久啊那么久,我果然秀逗了,,,, #define _CRT_SECURE_NO_WARNINGS # ...
- hdu 1253 胜利大逃亡(广搜,队列,三维,简单)
题目 原来光搜是用队列的,深搜才用栈,我好白痴啊,居然搞错了 三维的基础的广搜题 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #in ...
- (广搜)Fire Game -- FZU -- 2150
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82828#problem/I Fire Game Time Limit:1000MS ...
- 广搜 poj3278 poj1426 poj3126
Catch That Cow Time Limit: 2000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Ja ...
- hrbust 1621 迷宫问题II 广搜
题目链接:http://acm.hrbust.edu.cn/vj/index.php?/vj/index.php?c=&c=contest-contest&cid=134#proble ...
随机推荐
- c语言学习笔记 if语句的条件判断
可能经常会看到错误的if语句示范,比如这样的: if(a=6) { printf("hello"); } if语句块执行的条件是if条件的运算结果不是0则执行if语句块. a=6这 ...
- Ubuntu下成功安装台式机网卡realtek的rtl8188eu芯片驱动并实现AP功能
1,下载驱动 https://github.com/lwfinger/rtl8188eu 使用注意: https://github.com/lwfinger/rtl8188eu/issues/3 2. ...
- UVa 11149 Power of Matrix (矩阵快速幂,倍增法或构造矩阵)
题意:求A + A^2 + A^3 + ... + A^m. 析:主要是两种方式,第一种是倍增法,把A + A^2 + A^3 + ... + A^m,拆成两部分,一部分是(E + A^(m/2))( ...
- Linux下的strerror是否线程安全?
下列是glibc-2.14中的源代码: 点击(此处)折叠或打开 char * strerror (errnum) int errnum; { char *ret = __strerror_r (err ...
- delphi 取json中数组的值(ISuperArray)
{ "action": "******", "data": [ { "Info1": { "ID": ...
- Oracle 已连接到空闲例程或ORA-01034: ORACLE not available
因为是本地数据库没有重要资料,所以可以随便自己折腾. 出现问题原因:从生产数据库导入一个表到本地库测试,因数据量过大,在导入4-5个小时后,手动中断导入.是否异常关机不能确定. 之后再打开数据库出现一 ...
- 数据库表转换成JavaBean
本人花了几个小时用C#开发了一款,数据表生成javabean的软件.目前只支持Mysql,内置类型映射器.开源,没有测试. 支持数据库注释,忘了获取表注释,见谅.使用之前配置一下config.xml文 ...
- raiden_graph
使用mermaid描述 raiden 通道 AB,正常状态 graph LR A-- 60,100,S_100 ---B 通道 AB closed graph LR A((A)) -. 60,100 ...
- C# 向TIM或者QQ自动发送中文消息【微信也是可用的】 附测试GIF
之前用C++简单的写了一个demo 现在用C#写了完整版 定义字符 定义发送数量 定义发送对象 注意事项 QQ必须单独一个窗体 微信对象在输入名字的时候必须写微信 源代码 using System; ...
- React基础篇(2) -- state&props&refs
内容简介 state props refs 行内样式及动态类名 state 基本介绍 React 把组件看成是一个状态机(State Machines).通过与用户的交互,实现不同状态,然后渲染 UI ...