package main import . "fmt" type P struct { row,col int } func abs(a int) int { return max(-a,a) } func main() { var n int Scan(&n) ws := make([]*P,0,n*n) bs := make([]*P,0,n*n) ans := 0 for row := 0; row < n; row++ { var s string Scan(&s) for col, ch := range s { if col < n { if ch == '#' { if len(ws) > 0 { w := ws[0] ws = ws[1:] ans += abs(w.col-col)+abs(w.row-row) } else { bs = append(bs, &P{row,col}) } } } else if ch == '.' { if len(bs) > 0 { b := bs[0] bs = bs[1:] ans += abs(b.col-col)+abs(b.row-row) } else { ws = append(ws, &P{row,col}) } } } } Println(ans) } /* 考察 左半部にある黒と右半分にある白のペアのマンハッタン距離の総和が答えっぽい? 黒を移動可能オブジェとみなし、白を地面とみなしたときの、オブジェの移動量の総和として考えるみたいな? ペアの組み方は距離最小でペアを組んでく貪欲法でよさそう? ....#### .#...### ....#### ...#.### 距離貪欲だと失敗しそうな2例 ....#### 下の#はどちらの.とも距離は同じだが上の.とペアを作るとアウト #....### ....#### ...###.# .....### 上の#はどちらの.とも距離は同じだが下の.とペアを作るとアウト ..#.#### .....### .#..#### 違うっぽいなあ 横方向の移動は 左半分にある黒は真ん中を超える必要があり 右半分にある白も真ん中を超える必要があり どちらも中央の境界まで移動させるは移動先にかかわらず必須であり 中央に寄せたあとの状態について考えてみると 最上段の黒は最上段の白とペアでつぶしたほうがよく つまり 双方上から下へ貪欲にペアを作る もしくは双方下から上へ貪欲にペアを作る が最適ぽい? */