intさわだんのBlack History

刹那的レジェンドになりたい。

JOI本選過去問 第6回 日本情報オリンピック本選 3問目 最古の遺跡

問題文はこちら


長年頭の中では解けていたけど、実装していなかった問題。

解けて頭がすっきりした。


解説の効率のよい解法で計算量がO(n^2 log n)と書いていたのをみて、「これはO(n^2/2)でいけるのでは」と思って実装してみた。

やるだけでとてもかんたんだけど。

intで座標管理したらMemory Limit Exceededになったのでboolにしたら通りました。



Public Solutions で(たぶん)はじめて実行時間一番短かったのでうれしい。(すぐぬかされるな)

↓↓↓

http://judge.u-aizu.ac.jp/onlinejudge/solution.jsp?pid=0518

#include <cstdio>
#include <string.h>

using namespace std;

int n = 0;

int d[3004][2] = {0};

bool za[5003][5003] = {0};



int main(){

  while(1){

    long ans = 0;

  memset(d,0,sizeof(d));

  memset(za,0,sizeof(za));

  scanf("%d",&n);

  if(n == 0) break;

  for(int i = 0;i < n;i++){
    scanf("%d%d",&d[i][0],&d[i][1]);
    za[d[i][1]][d[i][0]] = true;
  }

  for(int i = 0;i < n;i++){
    for(int j = 0;j < i;j++){

      int sy = d[i][1] - d[j][1];
      int sx = d[i][0] - d[j][0];

      if((sy*sy + sx*sx) <= ans) continue;

      int k1x = d[i][0] + sy;
      int k1y = d[i][1] - sx;

      int k2x = d[j][0] + sy;
      int k2y = d[j][1] - sx;

      if(k1x < 0 || k1x > 5000 || k1y < 0 || k1y > 5000 || k2x < 0 || k2x > 5000 || k2y < 0 || k2y > 5000){
	continue;
      }

      if(za[k1y][k1x] == true && za[k2y][k2x] == true){
	ans =  (sy*sy + sx*sx);
      }

    }
  }

  printf("%ld\n",ans);

  }

  return 0;

}

(解説よくみたらこんな感じでできるとも書いてました。。。