cf div.2 #668
题意
给一个数字矩阵,对于每一个数,可以任意选两个数,加自己构造的一个点,组成三角形,问什么情况,三角形面积 * 2最大。
(这个三角形要求,至少有一条边平行于x轴或者y轴)
题解
这种三角形面积 * 2是 ∣ x a − x b ∣ ∗ ∣ y a − y c ∣ |x_a - x_b| * |y_a - y_c| ∣xa−xb∣∗∣ya−yc∣。
我原本考虑最角落4个点,but实现有点问题。
可以考虑每行的点,把所有 ∣ x a − x b ∣ |x_a - x_b| ∣xa−xb∣记录下来,再找面积最大的。
仔细来说:
对于某个数,记录横纵坐标最大最小值,
遍历每个等于这个数的点,与横纵坐标最大最小值的点找最大三角形的底和高
图
//是我没有想到过的,重点还是发现这个问题算面积只需找到底和高
提一嘴
一串无空格的字符串,无需用字符输入
可以scanf("%1d", &mp[i][j]);
#include <bits/stdc++.h>
using namespace std;
const int MAX = 2e3 + 10;
const int INF = 1e5 + 10;
int mp[MAX][MAX];
int n;
int ans[12];
inline void solve() {
int maxx[12], mppinx[12];
int maxy[12], miny[12];
fill(ans, ans + 12, 0);
fill(maxx, maxx + 12, -1); fill(maxy, maxy + 12, -1);
fill(minx, minx + 12, INF); fill(miny, miny + 12, INF);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
int d = mp[i][j];
maxx[d] = max(maxx[d], i);
minx[d] = min(minx[d], i);
maxy[d] = max(maxy[d], j);
miny[d] = min(miny[d], j);
}
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
int d = mp[i][j];
int res = max(n - j, j - 1) * max(maxx[d] - i, i - minx[d]);
ans[d] = max(ans[d], res);
res = max(n - i, i - 1) * max(maxy[d] - j, j - miny[d]);
ans[d] = max(ans[d], res);
}
}
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++)
scanf("%1d", &mp[i][j]);
}
solve();
for(int i = 0; i < 10; i++) {
printf("%d ", ans[i]);
}
cout << endl;
}
}