来自风平浪静的明天 (记忆化搜索 dp)
2017-09-18 08:48
155 查看
来自风平浪静的明天
【题目描述】冬眠了五年,光终于从梦中醒来。
千咲、要,大家都在。
隐约记得“昨天”的海船祭,爱花意外成为贡女,沉入海底。
海面冰封,却有丝丝暖流在冰面之下涌动。
此时,爱花沉睡在祭海女神的墓地。她的胞衣在一点点脱落,化作一簇簇暖流,夹杂着她的感情,向海面上涌去。
爱花,你在哪里?
五年之后,纺已经成为海洋学研究科的大学生。
在纺的帮助下,光得知了海面下海流的情况。
纺告诉光,暖流一旦产生,就会不断地向四周扩散,直到遇到海中的岩石。
红腹海牛,快告诉光,爱花在哪里。
纺帮你绘制了一张海流情况图,长度为N,宽度为M。
海很大,一边有沙滩,一边一望无际,但长度和宽度都不会超过300。沙滩是金黄色的,所以用Y表示。海是蓝色的,所以用B表示。暖流很暖和,所以用H表示
海中有大大小小的石头。石头很危险,所以用X表示
光相信自己一定能找到爱花(爱花的位置只有一种可能)
【输入格式】
第一行包括两个整数N,M。
接下来N行,每行M个字符。
【输出格式】
仅一行,表示爱花的位置(如果你无能为力,请输出 -1 ,只要你尽力,光不会责怪你)
【样例输入】
5 5
YYYHB
YYHHH
YHHXB
BBHBB
BBBBB
【样例输出】
2 3
【数据范围】
对于30%的数据,n,m<=10
对于70%的数据,n,m<=100
对于100%的数据,n,m<=300
【样例解释】
在(2,3)出现第一个H后,经过3s后,出现样例输入的地图。
P.S. Mushroom拜托他GF出的这题= =
思路:
看看数据范围,应该是一个n^3的算法,x,y一枚举就n^2了,然后。。。发现H最多就会漫延n+m次。
用dp[step][x][y]表示当前在(x,y),还要走step步是否能达到目标局面,也就是说是个bool。
那么对于当前这个点,如果是’B’并且step!=0那么当前状态显然是false,如果是石头或者沙滩,那么是true,如果当前step==0,那么返回(g[x][y]==’H’)。
数据太水,暴力dfs可过。。。
std的题解:
Solution
还记得以前解决过的那个问题吗?
水从一个点开始向四周漫去,一定时间后是什么样子?
显然是简单的模拟。
这次的问题正好相反,要找到水开始漫的位置。
Solution1
看了半天,什么也没发现。
天空突然电闪雷鸣,一个神奇的想法也就出现了。
YYYHB
YYHHH
YHHXB
BBHBB
BBBBB
这四个地方就是暖流的边界。
只有周围的四个格子是蓝蓝的大海或者石头和沙滩,才可能是暖流的边界。
我们可以把这些边界放进一个队列里,然后把图上变成大海。
YYYBB
YYHHB
YBHXB
BBBBB
BBBBB
然后就有了新的边界。
如此反复,最后剩下的暖流就是爱花的位置。
YYYBB
YYHBB
YBBXB
BBBBB
BBBBB
原来找到爱花这么容易。
时间复杂度O(N^2)
空间复杂度O(N^2)
恩,如果大海的结构这么简单的话,的确如此。
又看了半天,不得不佩服大海的深邃。
YYYHB
YYHHH
YHHXB
YXHXB
YYYYY
我们用之前的方法
YYYHB
YYHHH
YHHXB
YXHXB
YYYYY
放进队列,然后把它们变成大海
YYYBB
YYHHB
YHHXB
YXHXB
YYYYY
YYYBB
YYBBB
YHBXB
YXHXB
YYYYY
然后就成了这样,有两个位置看起来像是爱花所在的地方。
但事实并非如此。
YYYHB
YYHHH
YHHXB
YXHXB
YYYYY
爱花其实在这里。
Solution2
又想了半天。
看起来可以DP。
Flow[TIME][X][Y]表示暖流的初始位置是(X,Y),经过时间TIME以后,形成的图案会不会和海流图不相符(不应是H的地方出现了H则不相符,应出现H的地方没有出现H认为相符)
YYYHB
YYHHH
YHHXB
BBHBB
BBBBB
海流图
YYYBB
YYHHB
YBHXB
BBBBB
BBBBB
相符的图(蓝色部分应该出现H但没有出现)
YYYHH
YYHHH
YHHXH
BHHHB
BBHBB
不相符的图(红色部分不该出现H但出现了)
F[TIME][X][Y]=F[TIME-1][X-1][Y]&&F[TIME-1][X][Y-1]&&F[TIME-1][X+1][Y]&&F[TIME-1][X][Y+1]
记忆化DP 时间复杂度O(N^3) 空间复杂度 O(N^3)
找到最大的TIME,对应的X和Y就是爱花的位置。
因为光相信自己一定能找到爱花,所以爱花的位置确定(不会有两个位置满足条件)。
Solution3
更好的算法?
还得继续想吧。
#include <cstdio> #include <iostream> #include <cmath> #include <algorithm> #include <cstring> #include <queue> using namespace std; const int N = 305; char map ; bool f[N<<1] [2];//f[T][x][y]表示设x,y是张ansT 即牺 char ss ; int n,m; bool check(int T, int x, int y){ if( f[T][x][y][0] ) return f[T][x][y][1]; if(x==0 || y==0 || x==n+1 || y==m+1) return true; if(map[x][y] != 'H') return true; f[T][x][y][0] = true; if(T == 0) return f[T][x][y][1] = true; if(map[x-1][y]=='B' || map[x+1][y]=='B' || map[x][y-1]=='B' || map[x][y+1]=='B') return f[T][x][y][1] = false; f[T][x][y][1] = check(T-1,x-1,y) && check(T-1,x+1,y) && check(T-1,x,y-1) && check(T-1,x,y+1); return f[T][x][y][1]; } int main(){ freopen ("calm.in", "r", stdin); freopen ("calm.out", "w", stdout); scanf("%d%d", &n, &m); for(register int i=1; i<=n; i++){ scanf("%s", ss); for(register int j=1; j<=m; j++) map[i][j] = ss[j-1]; } for(register int t=n+m; t>=1; t--) for(register int i=1; i<=n; i++) for(register int j=1; j<=m; j++){ if(map[i][j] == 'H') check(t, i, j); if( f[t][i][j][1] ){ printf("%d %d", i, j); return 0; } } return 0; }
相关文章推荐
- 【搜索】 来自风平浪静的明天
- HDU 2476 String painter(记忆化搜索, DP)
- hdu 1978 How many ways(记忆化搜索dp)
- Codeforces Round #106(Div. 2) 149D. Coloring Brackets 区间DP 记忆化搜索
- HDU 5001 概率DP || 记忆化搜索
- BZOJ1055[HAOI2008]玩具取名 【区间dp + 记忆化搜索】
- uva 10453 - Make Palindrome (区间dp,记忆化搜索)
- 【SPOJ-RAONE】Ra-One Numbers【数位DP】【记忆化搜索】
- poj Function Run Fun(DP)(记忆化搜索)
- hdu1428 记忆化搜索(BFS预处理最短路径和+DP+DFS)
- POJ 2955 Brackets(区间DP, 记忆化搜索)
- hdu 1078 (记忆化搜索实现dp)
- codevs1255 搭积木——记忆化搜索,或者dp
- HDU 5900 QSC and Master (区间dp,记忆化搜索)
- UVA1351-----String Compression-----区间DP(记忆化搜索实现)
- UVA - 10003 Cutting Sticks(dp和记忆化搜索两种解法)
- Uva 437 DAG上的DP 记忆化搜索实现
- Codeforces 148D Bag of mice:概率dp 记忆化搜索
- uva 437 The Tower of Babylon(dp,记忆化搜索)
- DP-选课(记忆化搜索)