dp 练手题 题解

题面

题面:

在盖了一所正方形房子后,FJ 最近又得到了一块正三角形的土地,他也想在这块土地上建造一所房子,这次这个房子也必须是正三角形的。但是,这块土地并非十全十美,上面有很多不平坦的地方(也可以叫瑕疵)。这些瑕疵十分恶心,以至于根本不能在上面盖一砖一瓦。他希望找到一块最大的正三角形无瑕疵土地来盖房子。不过,这并不是什么难题,FJ 在 \(1\) 秒内就轻松解决了这个问题。现在,您也来试试吧。

如图所示,黑色的小正三角形表示瑕疵。

输入:

第一行,一个整数 \(n\),表示土地纵向划分为 \(n\) 行。

\(n\le 1000\)

接下来的 \(n\) 行,第 \(i\) 行包括了 \((n−i)\times 2+1\) 个有效字符。

- 表示这块土地是好的,# 表示这块土地有瑕疵。

为了保持三角形的形状,输入文件中会出现空格。

输出:

一行一个整数,表示最大的正三角形包括的小三角形数。

样例输入:

1
2
3
4
5
6
5
#-##----#
-----#-
---#-
-#-
-

样例输出:

1
9

我相信很多人和我一样看这题会想用二维前缀和做。

我试过了,比较麻烦。

下面介绍一种 DP 的方法。

思路

有两种三角形,正的(尖朝下),或者反的(尖朝上)。

我们设计状态:

a[i][j],以第 \(i\) 行,第 \(j\) 列为底三角形的最大可用三角形边长(\(j\bmod 2=1\));

b[i][j],以第 \(i\) 行,第 \(j\) 列为顶三角形的最大可用三角形边长(\(j\bmod 2=0\))。

正的

我们看 \(x\) 这个小三角形。

如果它是瑕疵,直接 a[i][j]=0

否则,可以从 \(y,z\) 转移过来,那么显然转移式子是:

1
a[i][j]=min(a[i-1][j],a[i-1][j+2])*(mp[i-1][j+1]=='-')+1;

mp 是存整个地图的数组。

另,我们的存储方式是:把所有三角形看成一个个点,然后往左压,具体见代码。

反的

同理。

如果它是瑕疵,直接 b[i][j]=0

否则,可以从下方转移过来,那么显然转移式子是:

1
b[i][j]=min(b[i+1][j-2],b[i+1][j])*(mp[i+1][j-1]=='-')+1;

所以行要从后向前遍历。

坑点

输入直接 cin

要取所有状态的 max

最后时求的是面积不是边长。

时间复杂度

\(O(n^2)\),能过。

甚至 \(n\) 可以到一万。

代码

致谢

教练 zxc,提供题目;

同学 whl,提供思路;

同学 zxz,提出可能的时间复杂度(虽然没做出来)。