首页 > 其他 > 详细

USACO20Feb Equilateral Triangles 【构造】【前缀和】

时间:2021-05-20 22:59:55      阅读:19      评论:0      收藏:0      [点我收藏+]

挺有趣的这题

虽然结论都是一样的,但是有两种思路看待这个问题:在曼哈顿距离下,和在切比雪夫距离下

(图片来自luogu)

我是从曼哈顿距离下看待这个问题的

技术分享图片

若这三点构成一个曼哈顿等边三角形,我们其实可是虚构一个点O出来

技术分享图片

图中A到C和B到C的换了路线,但是距离没有边,因为BC=AC且他们公用OC,BO=OA,那么我们就可以通过找等边三角形的方式先确定两个点

考虑第三个点C,我们发现一个45度的斜线上的所有点均满足要求,所以统计45度的前缀和即可

图中只是曼哈顿三角形的一个形式,还需要通过旋转整个图来匹配所有的形式

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define gi get_int()
const int MAXN = 600;
int get_int()
{
  int x = 0, y = 1;
  char ch = getchar();
  while (!isdigit(ch) && ch != ‘-‘)
    ch = getchar();
  if (ch == ‘-‘)
    y = -1, ch = getchar();
  while (isdigit(ch))
    x = x * 10 + ch - ‘0‘, ch = getchar();
  return x * y;
}

class Node
{
public:
  int x, y;
} num[MAXN * MAXN + 10];

int map[MAXN][MAXN], count[MAXN][MAXN], tmp[MAXN][MAXN], sum[MAXN][MAXN], n, cnt, ans;

void getAns()
{
  memset(sum, 0, sizeof(sum));
  for (int i = 0; i < n * 2; i++)
    for (int j = 0; j < n * 2; j++) {
      if (i == 0)
        sum[i][j] = map[i][j];
      else
        sum[i][j] = sum[i - 1][j + 1] + map[i][j];
    }
  for (int i = 0; i < cnt; i++) {
    for (int j = 1; j <= n; j++) {
      int nowX = num[i].x - j, nowY = num[i].y + j;
      if (nowX < 0 || nowY >= n) break;
      if (map[nowX][nowY] == 0) continue;
      ans += sum[num[i].x + j][num[i].y + j] - sum[num[i].x][num[i].y + 2 * j];
    }
  }
}

void prep()
{
  cnt = 0;
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++) {
      if (map[i][j] == 0) continue;
      num[cnt].x = i;
      num[cnt++].y = j;
    }
}

void flip()
{
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
      tmp[i][j] = map[i][j];
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++) {
      map[j][i] = tmp[n - i - 1][j];
    }
  prep();
}

int main()
{
  freopen("code.in", "r", stdin);
  freopen("code.out", "w", stdout);

  n = gi;
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++) {
      char ch;
      std::cin >> ch;
      if (ch == ‘*‘)
        map[i][j] = 1;
    }
  for (int i = 0; i < 4; i++) {
    flip();
    getAns();
  }
  std::cout << ans;

  return 0;
}

USACO20Feb Equilateral Triangles 【构造】【前缀和】

原文:https://www.cnblogs.com/enisP/p/14790501.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!