特にすぬけ君の塗り絵 2 イージーは1日中考えてしまった。
僕より理解が遅い方は多分いないと思いますがちょっとググってでてきたものより詳細な解説をしておこうw
まずこんな感じの面積を求める問題でした(イメージだと白色部分の面積を求める)
解き方1
賢い方は下記のような変数を作成して四辺の長さを常に更新するようなロジックでした。
またまたややこいのが、ケースごとによってどこを塗りつぶすか変わって来るところ
int left = 0; int right = w; int top = h; int bottom = 0;
それをこんな感じで対応されてました
この画像とかで見ると少しわかりやすくなる
if(a == 1) { left = Math.max(x, left); } else if(a == 2) { right = Math.min(x, right); } else if(a == 3) { bottom = Math.max(y, bottom); } else { top = Math.min(y, top); }
これをすると四辺の長さがでるので、あとは算数的に面積を求めるだけなんだけど
System.out.println(Math.max(right - left, 0) * Math.max(top - bottom, 0));
値がマイナスになることもあるので0積算になるようにすると。。 うーん、これ自分で思いつけるか?まー現時点ではきっぱり無理だなーと思いました。
追記5/26
復習していると、また下記のような乱雑なコードを再度書くのは面倒すぎたので、上記ロジックをひたすら理解するように頑張りました。
意外と理解してしまうと簡単で、要は下記を求めるためにMath.max()
やMath.min()
を使っているのだと理解しました。
- 埋められていない縦横の数値を導き出す
- 最大の縦の長さ(与えられた値、Hと呼ぶ)、現在の縦の長さ(初期値は0, CHと呼ぶ)、最大の横の長さ(与えられた値、Wと呼ぶ)、現在の横の長さ(初期値は0、CWと呼ぶ)の4変数をつくっておく
- 4つのケースによってどの変数を使うか考える
1. x < xi
なら、CWと与えられたnxの横の長さの値を比較して、大きい値をCW
に置き換える
2. x > xi
なら、Wと与えられたnxの横の長さの値を比較して、小さい値をW
に置き換える
3. y < yi
なら、CHと与えられたnxの縦の長さの値を比較して、大きい値をCH
に置き換える
4. y > yi
なら、Hと与えられたnxの縦の長さの値を比較して、大きい値をH
に置き換える
- 与えられた縦横の長さ(最大値)から求めた縦横の長さを引いて(W - CW)*(H - CH)
、埋められていない面積を求める
- この際に、どちらかまたは両方がマイナスになる場合(例2)があるので、最後にMath.max(求めた値,0)
を使っている(マイナス同士の積はプラスになることは完全に忘れてたので、単純に積がマイナスになるとも限らない)
解き方2
バケットソート?と言われるアルゴリズムを使って、自分らしいもっと単純で乱雑なコードを書きました。
- 面積分の二次元arrayを作成しておく
- 塗りつぶされた部分を1に置き換え
- 初期値の0の値がある場所を数える(二次元arrayの全探索)
これならなんとかACなりました。
しかし、実はこの問題面積を求めるだけなので塗りつぶし箇所が逆になっててもACでした。(笑)