解答・コメントを送る方法
コメントを送るには2つの方法があります。
- 匿名でコメントを書くログインせずにコメントを書くことができます。 名前は「匿名」となります。
- アカウントを作成してコメントを書くアカウントを作成すると、記名での投稿ができます。 また、プロフィールページが作成され、 簡単なプロフィールや 統計情報が表示されるようになります。
投稿ボタンを押す前に以下の文章を確認してください
- 当サイトへの投稿は クリエイティブ・コモンズ・ライセンス BY(表示)および、その解釈に同意するものとみなされます。各ページには下のようにライセンス表示が行われます。
- あなたの投稿したコード・コメント・トピックが再利用・添削されることを望まない場合は、投稿をお控えください。
- 自分が書いていない、ウェブサイトや書籍などからの無断コピーは著作権の侵害です。著作権者の了解を得るか、自分で0から書いてください。
- 著作権の侵害、名誉毀損、など投稿内容に問題がある場合、削除することがあります。
- これらのことにあなたはあらかじめ同意したものとみなされます。
Post comment
Post a comment to the following challenge:
情報オリンピック2007年度世界大会「洪水」
(Nested
Flatten)
As a reply to the following comment: yukoba: プログラムの制限時間もクリアしているバー...(#5763) [show]

yukoba #5763() [ Scala ] Rating0/0=0.00
以下が擬似コードです。
-------------------------------------
{まだたどっていない壁}がある
[全ての壁|座標でソート済み]in{まだたどっていない壁}から最初の壁をとる。次はこの配列番号から。
左手に水:int=頂点から右方向に壁 なら 1 下方向なら -1
最初の壁に戻ってくるまで、壁をたどる (do-while)
{たどった壁}に入っている => {たどった壁}から{両方水の壁}へ移動
else {まだたどっていない壁}から{たどった壁}へ移動
次の壁の始点=前の壁の終点
{次の壁の始点 -> つながっている壁|not in 両方水の壁 && 崩壊壁}から「角度」の小さい順にたどる
角度=外積(前の壁、次の壁)×左手に水(正負)-> 90~360
{たどった壁} => {崩壊壁}
{両方水の壁}を表示
-------------------------------------
package jp.yukoba.ioi2007; import scala.collection.mutable._ object Flood4 extends Application { class Base case class Point(x:int, y:int) extends Base { def < (that:Point) = (y < that.y || (y == that.y && x < that.x)) } case class Wall(no:int, from:Point, to:Point) extends Base { def < (that:Wall) = (from < that.from) } // 点番号 -> Point val N = readInt val dotMap = Map(List.tabulate(N, i => { val line = readLine.split(" ").map(Integer.parseInt(_)) (i+1, Point(line(0), line(1))) }):_*) // 壁番号 -> Wall val W = readInt val wallMap = Map(List.tabulate(W, i => { val ary = readLine.split(" ").map(Integer.parseInt(_)) // 左上に近いのを from に設定 val p1 = dotMap(ary(0)) val p2 = dotMap(ary(1)) if(p1 < p2) (i+1, Wall(i+1, p1, p2)) else (i+1, Wall(i+1, p2, p1)) }):_*) // 訪れていない壁番号のセット val unvisited:Set[int] = Set(wallMap.keys.toList:_*) // ソート済みの壁の壁番号の配列 val sortAry = wallMap.keySet.toList.sort((n1, n2) => wallMap(n1) < wallMap(n2)).toArray // 上のたどっていくポインタ var sortAryPos = 0 // {たどった壁} {両方水の壁} val visited = Set[int]() val bothWater = Set[int]() val brokenWall = Set[int]() // Point -> Wallの配列 val point2wallAry = Map[Point, Array[(Wall,int)]]() for(pointNo <- dotMap.keys) { // 頂点から出る壁は1~4つ val point = dotMap(pointNo) point2wallAry(point) = new Array[(Wall,int)](4) } for(wallNo <- unvisited) { def put(p:Point, wallDir:(Wall,int)) { val ary = point2wallAry(p) for(i <- 0 until (ary.length)) { if(ary(i) == null) { ary(i) = wallDir return } } error("ここにはこない") } val wall = wallMap(wallNo) put(wall.from, (wall, 1)) put(wall.to, (wall, -1)) } while(unvisited.size > 0) { //println(unvisited) // [全ての壁|座標でソート済み]in{まだたどっていない壁}から最初の壁をとる。次はこの配列番号から。 def getFromSortAry():int = { while(true) { val wallNo = sortAry(sortAryPos) if(unvisited.contains(wallNo)) return wallNo sortAryPos += 1 } error("ここにはこない") } var wallNo = getFromSortAry var wall = wallMap(wallNo) // 左手に水:int=頂点から右方向に壁 なら 1 下方向なら -1 val isLeftWater = if(wall.from.y == wall.to.y) 1 else -1 //println("isLeftWater = " + isLeftWater) // 壁のたどる方向、1 = from -> to、-1 = to -> from var wallDir = 1 // 最初の壁に戻ってくるまで、壁をたどる (do-while) val firstWallNo = wallNo val firstWallDir = wallDir def loop() { while(true) { //println("wall = " + wall + ", wallDir = " + wallDir) //{たどった壁}に入っている => {たどった壁}から{両方水の壁}へ移動 // else {まだたどっていない壁}から{たどった壁}へ移動 if(visited.contains(wallNo)) { visited -= wallNo bothWater += wallNo } else { unvisited -= wallNo visited += wallNo } // 次の壁の始点=前の壁の終点 val nextStart = (if(wallDir == 1) wall.to else wall.from) // {次の壁の始点 -> つながっている壁|not in 両方水の壁 && 崩壊壁}から「角度」の小さい順にたどる //println(nextStart) val wallAry = point2wallAry(nextStart) var minArg = Integer.MAX_VALUE var minWallDir:(Wall,int) = null for(i <- 0 until (wallAry.length)) { val nextWallDir = wallAry(i) //println("nextWallDir = " + nextWallDir) if(nextWallDir != null && !bothWater.contains(nextWallDir._1.no) && !brokenWall.contains(nextWallDir._1.no)) { // 角度=外積(前の壁、次の壁)×左手に水(正負)-> 90~360 def getArg(wall1:Wall, wallDir1:int, wall2:Wall, wallDir2:int, isLeftWater:int):int = { def toSign(p:Point):Point = Point(toSignI(p.x), toSignI(p.y)) def toSignI(i:int) = if(i<0) -1 else if(i==0) 0 else 1 def toVec(wall:Wall, wallDir:int) = if(wallDir == 1) Point(wall.to.x - wall.from.x, wall.to.y - wall.from.y) else Point(wall.from.x - wall.to.x, wall.from.y - wall.to.y) val vec1 = toSign(toVec(wall1, wallDir1)) val vec2 = toSign(toVec(wall2, wallDir2)) if(vec1 == vec2) return 180 else if(vec1.x == -vec2.x && vec1.y == -vec2.y) return 360 val gaiseki = (vec1.x * vec2.y - vec1.y * vec2.x) * isLeftWater if(gaiseki < 0) return 90 else return 270 } val arg = getArg(wall, wallDir, nextWallDir._1, nextWallDir._2, isLeftWater) //println("arg = " + arg) if(arg < minArg) { minArg = arg minWallDir = nextWallDir } } } //assert(minWallDir != null) if(minWallDir == null) return // 最初の壁に戻って来たら終了 val nextWall = minWallDir._1 val nextWallDir = minWallDir._2 if(nextWall.no == firstWallNo && nextWallDir == firstWallDir) return wall = nextWall wallDir = nextWallDir wallNo = wall.no } } loop() brokenWall ++= visited visited.clear } println(bothWater.size) for(wallNo <- bothWater) println(wallMap(wallNo).no) //println(brokenWall.size) }Rating0/0=0.00-0+