AOJ : 0193 - Deven-Eleven

問題概要

http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/description.jsp?id=0193&lang=jp
日本語の問題文なので説明は省略です

アルゴリズム

各マスから, 一番近い店への最小距離を記憶するマップを, 幅優先によって求めておきます.
候補地が入力されたら, その位置から幅優先を行います.
この際, マップに記憶されている値より, 候補地からの距離の方が小さいようなマスがあれば, カウントしていきます.
このカウント値が答えです.


※今回は, Hex座標なので, 幅優先で遷移していくとき, 偶数列と奇数列では, 遷移の仕方が異なるので注意です.

プログラム

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;

typedef pair<int,int> P;
typedef pair<P,int> PP;

#define REP(i,n,m) for(int i=n;i<m;i++)
#define rep(i,n) REP(i,0,n)
#define INF 999999999

int w,h,s,t;
int d[102][102]; //各マスから一番近い店への最小距離
bool closed[102][102]; //幅優先用

int dx1[] = { 0, 1, 1, 1, 0,-1}; //奇数列からの遷移
int dy1[] = {-1,-1, 0, 1, 1, 0}; //奇数列
int dx2[] = {-1, 0, 1, 0,-1,-1}; //偶数列
int dy2[] = {-1,-1, 0, 1, 1, 0}; //偶数列

//flg : マップを塗るか塗らないか
int draw(int x,int y,bool flg){
  int res = 0;
  queue<PP> q;
  memset(closed,0,sizeof(closed));

  q.push(PP(P(x,y),0));

  while(!q.empty()){
    PP p = q.front(); q.pop();
    int x = p.first.first;
    int y = p.first.second;
    if(closed[y][x]) continue;
    closed[y][x] = true;

    if(d[y][x] > p.second){
      if(flg) d[y][x] = p.second;
      res++;
    }

    for(int i=0;i<6;i++){
      int nx = x + (y%2==1 ? dx1[i] : dx2[i]);
      int ny = y + (y%2==1 ? dy1[i] : dy2[i]);
      if(nx>=0 && nx<w && ny>=0 && ny<h){
        q.push(PP(P(nx,ny),p.second+1));
      }
    }
  }
  return res;
}

int main(void){
  while(cin>>w>>h,w){
    rep(i,h) rep(j,w) d[i][j] = INF;

    cin>>s;
    rep(i,s){
      int p,q;
      cin>>p>>q;
      draw(p-1,q-1,true);
    }

    int ans = 0;
    cin>>t;
    rep(i,t){
      int p,q;
      cin>>p>>q;
      ans = max(ans,draw(p-1,q-1,false));
    }

    cout<<ans<<endl;
  }

  return 0;
}