NOIP模拟题——来自风平浪静的明天
【题目描述】
冬眠了五年,光终于从梦中醒来。
千咲、要,大家都在。
隐约记得“昨天”的海船祭,爱花意外成为贡女,沉入海底。
海面冰封,却有丝丝暖流在冰面之下涌动。
此时,爱花沉睡在祭海女神的墓地。她的胞衣在一点点脱落,化作一簇簇暖流,夹杂着她的感情,向海面上涌去。
爱花,你在哪里?
五年之后,纺已经成为海洋学研究科的大学生。
在纺的帮助下,光得知了海面下海流的情况。
纺告诉光,暖流一旦产生,就会不断地向四周扩散,直到遇到海中的岩石。
红腹海牛,快告诉光,爱花在哪里。
纺帮你绘制了一张海流情况图,长度为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出的这题= =
题目写的真好~~~~~~~~~~只是我看不懂。
后来才晓得一开始给的图只是一个普通状态而不是最终状态(所以就误将碰到石头理解为再向下漫延一次就停下来了。。)
正解:f[T][x][y]表示从map[x][y]开始,漫延时间为T的情况是否匹配
(不应是H的地方出现了H则不相符,应出现H的地方没有出现H认为相符)
YYYHB
YYHHH
YHHXB
BBHBB
BBBBB
海流图
YYYBB
YYHHB
YBHXB
BBBBB
BBBBB
相符的图(蓝色部分应该出现H但没有出现)
YYYHH
YYHHH
YHHXH
BHHHB
BBHBB
不相符的图(红色部分不该出现H但出现了)
于是得到DP方程:F[T][X][Y]=F[T-1][X-1][Y]&&F[T-1][X][Y-1]&&F[T-1][X+1][Y]&&F[T-1][X][Y+1]
时间复杂度O(n³)
1 #include<cstdio>
2 #include<iostream>
3 #include<cmath>
4 #include<algorithm>
5 #include<cstring>
6 using namespace std;
7 const int maxn=305;
8 char map[maxn][maxn];
9 bool f[2*maxn][maxn][maxn];
10 bool pd[2*maxn][maxn][maxn];
11 char c[maxn];
12 int n,m;
13 bool solve(int T,int x,int y)
14 {
15 if(pd[T][x][y])return f[T][x][y];
16 if(x==0||y==0)return true;
17 if(x==n+1||y==m+1)return true;
18 if(map[x][y]!='H')return true;
19 if(T==0)
20 {
21 pd[T][x][y]=true;
22 f[T][x][y]=true;
23 return true;
24 }
25
26 if(map[x-1][y]=='B'||map[x+1][y]=='B'||map[x][y-1]=='B'||map[x][y+1]=='B')
27 {
28 pd[T][x][y]=true;
29 f[T][x][y]=false;
30 return false;
31 }
32
33 pd[T][x][y]=true;
34 f[T][x][y]=solve(T-1,x-1,y)&&solve(T-1,x+1,y)&&solve(T-1,x,y-1)&&solve(T-1,x,y+1);
35 return f[T][x][y];
36 }
37 int main()
38 {
39 freopen("calm.in","r",stdin);
40 freopen("calm.out","w",stdout);
41 scanf("%d%d",&n,&m);
42 for(int i=1;i<=n;i++)
43 {
44 scanf("%s",c);
45 for(int j=1;j<=m;j++)
46 map[i][j]=c[j-1];
47 }
48 for(int i=1;i<=n+m;i++)
49 for(int j=1;j<=n;j++)
50 for(int k=1;k<=m;k++)
51 {
52 if(map[j][k]=='H')
53 solve(i,j,k);
54 }
55 for(int i=n+m;i>=1;i--)
56 for(int j=1;j<=n;j++)
57 for(int k=1;k<=m;k++)
58 {
59 if(f[i][j][k])
60 {
61 printf("%d %d",j,k);
62 return 0;
63 }
64 }
65 return 0;
66 }
这个DP方程真心NB,考场上能想到这样做就幸福了~