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) for i := range path { path[i] = 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 i := range c { if i < m/2 { c[i] = (i/3+1)*250 d[i] = (i%3+1)*250 } else { c[i] = ((i+1)/3+1)*250 d[i] = ((i+1)%3+1)*250 } } ccc := make([]int, m) cccc := 1 ccce := m for q := 0; q < 70; q++ { var oldi, oldc, oldd int if q > 0 { tmp := rand.Intn(ccce)+1 for i, cc := range ccc { tmp -= cccc - cc if tmp <= 0 { oldi = i break } } oldc, oldd = c[oldi], d[oldi] c[oldi] += rand.Intn(300+1) - 150 d[oldi] += rand.Intn(300+1) - 150 c[oldi] = max(0, min(1000, c[oldi])) d[oldi] = max(0, min(1000, d[oldi])) } for i := range path { 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]) } ccc[oldi]++ cccc++ ccce += m-1 } else if q > 0 && sc > bestSc { c[oldi] = oldc d[oldi] = oldd } } for i := range bestC { Println(bestC[i], bestD[i]) } Println(len(bestT)) for i := range bestT { Println(bestT[i], bestR[i]) } }