groovyの勉強:ACM/ICPCの問題を解く
本日の題材は、2010年国内予選の問題B。きっと二番目に簡単な奴。
http://icpc2010.honiden.nii.ac.jp/domestic-contest/problems#section_B
問題Aのときと同じように、eclipse開発だから、ファイルへの入出力へと変更した。
まあ、工夫したところはあまりなく、幅優先探索各セルのコストを求めつつ、番兵とかのテクニックを使ったことぐらいかなあ。幅優先探索だから、実際には、すでに計算済みのコストが上書きされることもないし、ゴールに着いたらループを抜けても良いんだけど、なんとなく、ガードをしておいた。
package acm.jp2010p String.metaClass.toIntegers = { delegate.trim().split(/\s+/)*.toInteger() } String.metaClass.toMapIntegers = { list -> [list, delegate.toIntegers()].transpose().collectEntries{it} } lines = new File(args[0]).readLines() new File(args[1]).withPrintWriter { out -> while( true ){ size = lines.remove(0).toMapIntegers(['width', 'height']) if( size.width == 0 && size.height == 0 ){ break } hwall = [[1]*size.width] // 横の壁 vwall = [] // 縦の壁 for( int y=0; y<size.height; y++ ){ vwall << [1]+lines.remove(0).toIntegers()+[1] if( y < size.height-1 ){ hwall << lines.remove(0).toIntegers() } } hwall << [1]*size.width costs = [] size.height.times { costs << [Integer.MAX_VALUE]*size.width } queue = [[x:0, y:0, c:1]] costs[0][0] = 1 while( queue.size() > 0 ){ c = queue.remove(0) if( hwall[c.y][c.x] == 0 && costs[c.y-1][c.x] > c.c+1 ){ queue << [x:c.x, y:c.y-1, c:c.c+1] costs[c.y-1][c.x] = c.c+1 } if( hwall[c.y+1][c.x] == 0 && costs[c.y+1][c.x] > c.c+1 ){ queue << [x:c.x, y:c.y+1, c:c.c+1] costs[c.y+1][c.x] = c.c+1 } if( vwall[c.y][c.x] == 0 && costs[c.y][c.x-1] > c.c+1 ){ queue << [x:c.x-1, y:c.y, c:c.c+1] costs[c.y][c.x-1] = c.c+1 } if( vwall[c.y][c.x+1] == 0 && costs[c.y][c.x+1] > c.c+1 ){ queue << [x:c.x+1, y:c.y, c:c.c+1] costs[c.y][c.x+1] = c.c+1 } } if( costs[size.height-1][size.width-1] == Integer.MAX_VALUE ){ out.println 0 } else { out.println costs[size.height-1][size.width-1] } } }
今回覚えたこと。
結局、今回も分からなかったこと。
- 多次元配列の楽な作り方