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,考场上能想到这样做就幸福了~

原文地址:https://www.cnblogs.com/937337156Zhang/p/6017461.html