問題概要
始め頂点(0,0)にいる。1回の操作で隣接する格子点を1つ選んで移動することができる。ただし、 かつ を満たす範囲には障害物があり移動することが出来ない。 回以内の操作で到達可能な格子点の総数を求めよ。
制約
解法
まず障害物が無い時を考える。この時、黒の菱形部分が到達可能範囲である。
この範囲にある格子点の数は容易に求めることが出来て、
となる。後ろの は での重複分である。
次に障害物ありの場合を考える.。制約より の部分は影響を受けないので正の部分だけ考えれば良い.。
重要なポイントとして、 の範囲における格子点は障害物の影響を受けずに到達可能である。
従って、 の範囲を探索し、障害物の影響で到達出来なくなった頂点を引いていけば答えが得られる。
注意するのは長方形の左右から回り込んで長方形より上の頂点に到達する場合で、この時は右回りのコストと左回りのコストを比較してその における到達可能な頂点の座標の範囲を求める。
実装
#include <iostream> #include <algorithm> using namespace std; typedef long long int ll; class RectangularObstacle { public: long long countReachable(ll x1, ll x2, ll y1, ll y2, ll s) { ll res=2*(s+1)*(s+1)-(2*s+1); for(ll x=x1;x<=x2;x++){ if(abs(x)>s)continue; ll t=s-abs(x); //長方形が無かった時に到達可能なy座標の最大値 if(t<y1)continue; if(t<=y2){ res-=(t-y1+1); } else{ res-=(y2-y1+1); ll cost=min(abs(x1)+y2+2+abs(x-x1),abs(x2)+y2+2+abs(x-x2)); ll can=max(0LL,s-cost); ll no=t-y2; // 元々到達可能で長方形の上側にある頂点数 can=min(can,no); res-=(no-can); } } return res; } };