[DP] 三角蛋糕 题解

题目描述

XP在机房里放了一块正三角形的大蛋糕,但是第二天他发现蛋糕被老鼠咬坏了。

image

XP不想让蛋糕白白的被浪费,于是他把蛋糕分割成了一个个的小正三角形(如上图所示)。黑色的小正三角形表示老鼠把那一块咬坏了。XP想要切出一块最大的没被老鼠咬坏正三角形的蛋糕,可是最大的三角形有多大呢?

输入格式

第一行,一个整数N,表示XP把蛋糕纵向划分为N行。 接下来的N(N<=100)行,第i行包括了(n-i)*2+1个有效字符。“0”表示这块蛋糕是好的,“1”表示这块蛋糕被咬坏了。为了保持三角形的形状,输入文件中会出现空格。

输出格式

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

样例

样例输入

5
101100001
 0000010
  00010
   010
    0

样例输出

9

题解

这道题让我不由自主地想起了盖房子,有兴趣可以看一看;

类比盖房子:

本题特殊之处:

首先需要预处理,将输入左对齐(过滤空格)(不左对齐也行,但左对齐后便于处理),这一步我处理的特别麻烦,大家作为参考,不要效仿(因为我也有些看不懂我写的。。。);

然后引入关于本题的一个重要结论:最大的三角形包括的小三角形数 = 高的平方(自己画几个图就能理解,在此不再赘述);

注意将1改成0,0改成1,便于以后加法操作;
相同之处:

其实这俩题思路一样,仍然是找最基本的小正三角形

  1
111

如上,并将信息存储在最上方的小三角形中(存在哪都一样,因人而异),然后利用短板效应找min值更新信息,最后找出最大值即为答案;

但会有一个问题:

特殊数据

1000000
 00001
  000
   0

image

注意中间的四个红色标记的小三角形,虽然满足上述情况,但并不能构成我们想要的正三角形;

发现问题出在三角形的朝向不一;

漏掉了向下的三角形;

1
111

因此我们需要处理两次,分别找出朝上和朝下的三角形最大值,最后找出总最大值即可;

代码

#include <iostream>
#include <cstring>
using namespace std;
int n;
char a[1005][1005];
int b[1005][1005];
int c[1005][1005];
int main() {
	cin >> n;
	int o = 1;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= 2 * n - o; j++) {
			cin >> a[i][j];
		}
		o += 2; //输入有些麻烦,尽量不要效仿;
	}
	o = 1;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= 2 * n - o; j++) {
			if (a[i][j] == '1') {
				b[i][j] = 0;
			}
			if (a[i][j] == '0') {
				b[i][j] = 1;
			} //参考盖房子;将1换成0,0换成1;
		}
		o += 2;
	} //左对齐;
	memcpy(c, b, sizeof(b)); //复制一个新数组,便于以后操作两次;
	o = 1;
	int ans = -1;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= 2 * n - o; j += 2) { //注意这里的j += 2,因为我们只找一个朝向的,而一个朝向隔一个出现一次;
			if (b[i][j] && b[i - 1][j] && b[i - 1][j + 1] && b[i - 1][j + 2]) { //四个都是合法的才可能;
				b[i][j] = min(b[i - 1][j], b[i - 1][j + 2]) + 1; //短板效应,找最小高度+本身高度(1);
			}
			ans = max(ans, b[i][j]); //ans找最大;
		}
		o += 2;
	}
	o = 2 * n - 1;
	for (int i = n; i >= 1; i--) { //倒序循环找三角形尖向上的;
		for (int j = 2; j <= 2 * n - o; j += 2) {
			if (c[i][j] && c[i + 1][j] && c[i + 1][j - 1] && c[i + 1][j - 2]) {
				c[i][j] = min(c[i + 1][j], c[i + 1][j - 2]) + 1;
			}
			ans = max(ans, c[i][j]);
		}
		o -= 2;
	}
	cout << ans * ans; //高的平方;
	return 0;
}

后记:同机房大佬也写了这道题的题解

posted @ 2024-02-16 08:52  Peppa_Even_Pig  阅读(58)  评论(0编辑  收藏  举报