こんにちは、ナナオです。

前回に引き続き競プロを実施していきたいと思います。

今回はAtCoderの問題を解いていきます。

問題は以下です。

004 - Cross Sum(★2)

実装

二次元の累積和ですね。

とりあえず愚直に解いてみます。

package main
import "fmt"
func main() {
  var h, w int
  fmt.Scan(&h, &w)
  g := make([][]int, h)
  for i := 0; i < h; i++ {
    g[i] = make([]int, w)
    for j := 0; j < w; j++ {
      fmt.Scan(&g[i][j])
    }
  }
  hg := make([]int, h)
  for i := 0; i < h; i++ {
    s := 0
    for j := 0; j < w; j++ {
      s += g[i][j]
    }
    hg[i] = s
  }
  wg := make([]int, w)
  for i := 0; i < w; i++ {
    s := 0
    for j := 0; j < h; j++ {
      s += g[j][i]
    }
    wg[i] = s
  }
  ans := make([][]int, h)
  for i := 0; i < h; i++ {
    ans[i] = make([]int, w)
    for j := 0; j < w; j++ {
      ans[i][j] = hg[i] + wg[j] - g[i][j]
    }
  }
  for i := 0; i < h; i++ {
    for j := 0; j < w; j++ {
      if j < w - 1 {
        fmt.Printf("%d ", ans[i][j])
      } else {
        fmt.Printf("%d", ans[i][j])
      }
    }
    fmt.Println()
  }
}

ですがこれだとタイムオーバーしてしまいました。

なんでやねん。

解説記事を見つつ、一部のコードを修正しました。

package main
import "fmt"
func main() {
  var h, w int
  fmt.Scan(&h, &w)
  g := make([][]int, h)
  hg := make([]int, h)
  wg := make([]int, w)
  for i := 0; i < h; i++ {
    g[i] = make([]int, w)
    for j := 0; j < w; j++ {
      fmt.Scan(&g[i][j])
      hg[i] += g[i][j]
      wg[j] += g[i][j]
    }
  }
  for i := 0; i < h; i++ {
    for j := 0; j < w; j++ {
      if j < w - 1 {
        fmt.Printf("%d ", hg[i] + wg[j] - g[i][j])
      } else {
        fmt.Printf("%d", hg[i] + wg[j] - g[i][j])
      }
    }
    fmt.Println()
  }
}

横軸と縦軸の計算と出力時の計算をそれぞれ一つのループ内にまとめることで、計算量を減らすことができました。

これで実行してみましたが、やはり実行速度が遅く…なぜ…

通っているパターンのGoのコードを見ながら少し修正しました。

package main
import (
  "bufio"
  "os"
  "fmt"
)
func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

  var h, w int
  fmt.Fscan(in, &h, &w)
  g := make([][]int, h)
  hg := make([]int, h)
  wg := make([]int, w)
  for i := 0; i < h; i++ {
    g[i] = make([]int, w)
    for j := 0; j < w; j++ {
      fmt.Fscan(in, &g[i][j])
      hg[i] += g[i][j]
      wg[j] += g[i][j]
    }
  }
  for i := 0; i < h; i++ {
    for j := 0; j < w; j++ {
      fmt.Fprint(out, hg[i] + wg[j] - g[i][j])
      if j < w - 1 {  
        fmt.Fprint(out, " ")
      }
    }
    fmt.Fprintln(out)
  }
}

これなら通るんですね。ロジックじゃない部分で通らないってこともあるんですね。。。

Goは早い言語だと思ってたですが、そうでもないかも…

というわけで今回はこれで👍