package main import . "fmt" import "math/rand" const ALPHA = 5 func dist(a,b []int, i int, c,d []int, j int) int { dx := a[i] - c[j] dy := b[i] - d[j] return dx*dx + dy*dy } func main() { var n, m int Scan(&n, &m) a := make([]int, n) b := make([]int, n) for i := range a { Scan(&a[i],&b[i]) } c := make([]int, m) d := make([]int, m) path := make([][][]int, n+m) p := []int{0} for i := 0; i < n; i++ { p = append(p, (i+1)%n) } calc := func(p []int) int { sc := 0 for i := 0; i < n; i++ { sc += path[p[i]][p[i+1]][0] } return sc } bestSc := int(1e9) bestC := make([]int, m) bestD := make([]int, m) bestT := make([]int, 0, 5000) bestR := make([]int, 0, 5000) var add func(i, j int) add = func(i, j int) { rt := path[i][j] if rt[1] == j { if j < n { bestT = append(bestT, 1) bestR = append(bestR, j+1) } else { bestT = append(bestT, 2) bestR = append(bestR, j-n+1) } return } add(i, rt[1]) add(rt[1], j) } for q := 0; q < 50; q++ { for i := range c { for k := 0; k < 10; k++ { c[i] = rand.Intn(500)+250 d[i] = rand.Intn(500)+250 ok := true for j, vc := range c[:i] { vd := d[j] dx := c[i] - vc dy := d[i] - vd ok = ok && (dx*dx+dy*dy>150*150) } if ok { break } } } for i := range path { path[i] = make([][]int, n+m) for j := range path[i] { switch { case i == j: path[i][j] = []int{ 0, j } case i < n && j < n: path[i][j] = []int{ ALPHA*ALPHA*dist(a,b,i,a,b,j), j, } case i < n: path[i][j] = []int{ ALPHA*dist(a,b,i,c,d,j-n), j, } case j < n: path[i][j] = []int{ ALPHA*dist(c,d,i-n,a,b,j), j, } default: path[i][j] = []int{ dist(c,d,i-n,c,d,j-n), j, } } } } for i := 0; i < n+m; i++ { for j := 0; j < n+m; j++ { if i == j { continue } for k := 0; k < n+m; k++ { if i==k || j==k { continue } if x := path[i][k][0]+path[k][j][0]; x < path[i][j][0] { path[i][j][0] = x path[i][j][1] = k } } } } for cc, changed := 0, true; changed && cc < 20; cc++ { changed = false // 2-opt ? for i := 1; i < n; i++ { for j := i+1; j < n; j++ { s0 := path[p[i-1]][p[i]][0] + path[p[j]][p[j+1]][0] s1 := path[p[i-1]][p[j]][0] + path[p[i]][p[j+1]][0] if s1 < s0 { for f,e := i,j; f < e; f,e=f+1,e-1 { p[f],p[e] = p[e],p[f] } changed = true } } } // 3-opt ? for i := 1; i < n; i++ { for j := i+1; j < n; j++ { for k := j+2; k < n; k++ { s0 := path[p[i-1]][p[i]][0] + path[p[j]][p[j+1]][0] + path[p[k]][p[k+1]][0] s1 := path[p[i-1]][p[j]][0] + path[p[i]][p[k]][0] + path[p[j+1]][p[k+1]][0] if s1 < s0 { for f,e := i,j; f < e; f,e=f+1,e-1 { p[f],p[e] = p[e],p[f] } for f,e := j+1,k; f < e; f,e=f+1,e-1 { p[f],p[e] = p[e],p[f] } changed = true } } } } } if sc := calc(p); sc < bestSc { bestSc = sc copy(bestC, c) copy(bestD, d) bestT = append(bestT[:0], 1) bestR = append(bestR[:0], 1) for i := 0; i < n; i++ { add(p[i], p[i+1]) } } } for i := range bestC { Println(bestC[i], bestD[i]) } Println(len(bestT)) for i := range bestT { Println(bestT[i], bestR[i]) } }