[编程题]石头碰撞
我们可以考虑以下过程:
把石头分为两堆,从A堆中取出一块石头m,B堆中取出n,不妨设m>=n。
碰撞后碎片为m-n,应放入A堆。
对比碰撞前后,你会发现两个堆的质量之差没有发生变化。并且重复碰撞下去直到只剩一堆的时候,你会发现剩下的质量就是两堆之差。真的是非常的巧妙,所以为了使最终剩余的质量最小,我们应该让两堆石头的质量尽可能接近,也就是尽量平均。
另外,这里的内层for很巧妙。我最开始写的是i++,这样会导致v的重复利用。比如v是一块20的石头,那么20,40,60…都会被标记为true。采用递减循环就可以避免这个问题。
package main
import (
"fmt"
)
func main() {
var n, tmp, sum, max int
var w []int
fmt.Scan(&n)
for i := 0; i < n; i++ {
fmt.Scan(&tmp)
sum += tmp
w = append(w, tmp)
}
flag := make([]bool, sum/2+1)
flag[0] = true
for _, v := range w {
for i := sum / 2; i >= v; i-- {
flag[i] = flag[i] || flag[i-v]
}
}
for i := sum / 2; i >= 0; i-- {
if flag[i] {
fmt.Print(sum - 2*i)
break
}
}
}