解答・コメントを送る方法

コメントを送るには2つの方法があります。
  • 匿名でコメントを書く
    ログインせずにコメントを書くことができます。 名前は「匿名」となります。
  • アカウントを作成してコメントを書く
    アカウントを作成すると、記名での投稿ができます。 また、プロフィールページが作成され、 簡単なプロフィールや 統計情報が表示されるようになります。
どちらの場合も投稿後の修正・削除はできないので、 投稿前によくご確認下さい。

投稿ボタンを押す前に以下の文章を確認してください

  • 当サイトへの投稿は クリエイティブ・コモンズ・ライセンス BY(表示)および、その解釈に同意するものとみなされます。各ページには下のようにライセンス表示が行われます。
    Creative Commons License このサイトの内容は、 クリエイティブ・コモンズ・ライセンスの下でライセンスされています。 [詳細]
  • あなたの投稿したコード・コメント・トピックが再利用・添削されることを望まない場合は、投稿をお控えください。
  • 自分が書いていない、ウェブサイトや書籍などからの無断コピーは著作権の侵害です。著作権者の了解を得るか、自分で0から書いてください。
  • 著作権の侵害、名誉毀損、など投稿内容に問題がある場合、削除することがあります。
  • これらのことにあなたはあらかじめ同意したものとみなされます。

Post comment

Post a comment to the following challenge: 情報オリンピック2007年度世界大会「洪水」 (Nested Flatten)

As a reply to the following comment: yukoba: プログラムの制限時間もクリアしているバー...(#5763) [show]

[hide]
プログラムの制限時間もクリアしているバージョン。
以下が擬似コードです。

-------------------------------------

{まだたどっていない壁}がある
  [全ての壁|座標でソート済み]in{まだたどっていない壁}から最初の壁をとる。次はこの配列番号から。
  左手に水:int=頂点から右方向に壁 なら 1 下方向なら -1
  最初の壁に戻ってくるまで、壁をたどる (do-while)
    {たどった壁}に入っている => {たどった壁}から{両方水の壁}へ移動
      else {まだたどっていない壁}から{たどった壁}へ移動
    次の壁の始点=前の壁の終点
    {次の壁の始点 -> つながっている壁|not in 両方水の壁 && 崩壊壁}から「角度」の小さい順にたどる
      角度=外積(前の壁、次の壁)×左手に水(正負)-> 90~360
  {たどった壁} => {崩壊壁}
{両方水の壁}を表示

-------------------------------------
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
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)
}


コメント本文
形式 [?]
コード
言語

タグ
半角スペースで区切って複数のタグを入力できます。
参考ページタイトル

参考ページURL
利用規約を読んで同意する必要があります。
by guest

Index

Feed

Other

Link

Pathtraq

loading...