生产消费者——生产消费者(1:n)模型
, main
函数是主线程,而二分的函数开一个线程,check
函数开100个线程,二分生产了mid
以后,传到通道,这100个check
函数线程会随机一个拿到mid
值,并生产check
的结果,然后二分线程拿到该结果再继续进行下去。
golang
的标准读入特别慢,需要1300+ms
才能跑完,这里改成了文件读入,速度不比C++
慢,仅用83ms
就跑完了。
ps: 因为golang的fmt.Scanf
、fmt.Scan
、fmt.Printf
、fmt.Println
都使用到了反射,golang中的反射性能非常的差,所以会严重拖慢执行效率。
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"sync"
)
type Node struct {
h, w int
}
var (
n, k int
arr = make([]Node, 100000)
wg sync.WaitGroup
ch = make(chan int, 1)
judge = make(chan bool, 1)
)
func main() {
fmt.Scanf("%d %d", &n, &k)
sc := bufio.NewScanner(os.Stdin)
sc.Split(bufio.ScanWords)
for i := 0; i < n; i++ {
sc.Scan()
arr[i].h, _ = strconv.Atoi(sc.Text())
sc.Scan()
arr[i].w, _ = strconv.Atoi(sc.Text())
}
wg.Add(1)
go func() {
l, r := 1, 100000
for l < r {
mid := (l + r + 1) >> 1
ch <- mid
if <-judge {
l = mid
} else {
r = mid - 1
}
}
fmt.Println(l)
wg.Done()
}()
// check函数,开100个协程
for i := 0; i < 100; i++ {
go func() {
tot := 0
num := <-ch
for i := 0; i < n; i++ {
tot += (arr[i].h / num) * (arr[i].w / num)
if tot >= k {
judge <- true
return
}
}
judge <- false
}()
}
wg.Wait()
}