CF1453C 三角形
1 CF1453C 三角形
2 题目描述
Gildong有一个正方形板,由\(𝑛\)行和\(𝑛\)列的正方形单元组成,每个单元由一个一位数(从 \(0\) 到 \(9\))组成。\(𝑖\) 行 \(𝑗\) 列处的单元格可表示为 \((𝑖,𝑗)\),每个单元格的边长为 \(1\)。Gildong喜欢大的东西,所以对于每一个数字 \(𝑑\),他想找到一个这样的三角形:
三角形的每个顶点都在一个单元格的中心。
三角形的每个顶点的数字都是 \(𝑑\)。
三角形的至少一侧与板的一侧平行。可以假设长度为 \(0\) 的一侧与板的两侧平行。
三角形的面积最大。
当然,他不能只对找到这些三角形感到高兴。因此,对于每个数字 \(𝑑\),他将把板的一个单元格的数字改为 \(𝑑\),然后找到这样的三角形。他在处理完每个数字后把它改回原来的数字。求他能为每个数字所做的三角形的最大面积。
注意,他可以把三角形的多个顶点放在同一个单元格上,三角形可以是简并三角形;即。 三角形的面积可以是\(0\)。此外,注意他可以将单元格的数字从 \(𝑑\) 更改为 \(𝑑\)。
3 解题思路
分析性质,我们发现,算出的最终值肯定有一个节点是修改过的(将 \(k\) 修改成 \(k\) 也可以)。从这一点出发,我们可以想到:对于任意一个已经确定的节点,在其所在的行或者列的四个极端(最上,最下,最左,最右)确定第二个节点,并取这个节点与这四个节点在水平方向长度的最大值,作为底,并找到相反方向的最长的长度作为高(比如选择了最左,那就找当前列最上和最下哪一个离当前节点最远并作为高。这时假设当前节点的坐标为 \((x, y)\),最上、最下的节点距离这个节点的距离最大为 \(m\),那么此时答案的值就是 \((y-1) * m\))。
这样我们就能确定出以每一个节点为顶点之一的最大面积,之后枚举每一个存在的节点计算面积即可(这里的节点意为在寻找以 \(k\) 为顶点的最大面积时值为 \(k\) 的点)。
4 代码(空格警告):
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
using namespace std;
const int N = 2005;
int T, n, x, y, digit;
char digi;
queue< pair<int, int> > q[10];
int lg[10], rg[10], ug[10], dg[10];
int ans[10];
int main()
{
scanf("%d", &T);
while (T--)
{
memset(lg, 0x3f, sizeof(lg));
memset(rg, 0, sizeof(rg));
memset(ug, 0x3f, sizeof(ug));
memset(dg, 0, sizeof(dg));
memset(ans, 0, sizeof(ans));
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
cin >> digi;
digit = (digi - '0');
q[digit].push(make_pair(i, j));
lg[digit] = min(lg[digit], j);
rg[digit] = max(rg[digit], j);
ug[digit] = min(ug[digit], i);
dg[digit] = max(dg[digit], i);
}
}
for (int i = 0; i <= 9; i++)
{
while (q[i].size())
{
x = q[i].front().first;
y = q[i].front().second;
ans[i] = max(ans[i], max(y-1, n-y) * max(x - ug[i], dg[i] - x));
ans[i] = max(ans[i], max(x-1, n-x) * max(y - lg[i], rg[i] - y));
q[i].pop();
}
}
for (int i = 0; i <= 9; i++) printf("%d ", ans[i]);
puts("");
}
return 0;
}