← Home
```go
package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
)

type Pt struct {
	x int64
	y int64
}

func cross(a, b, c Pt) int64 {
	return (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x)
}

func lessAround(pts []Pt, c, p, q int) bool {
	dx1 := pts[p].x - pts[c].x
	dy1 := pts[p].y - pts[c].y
	dx2 := pts[q].x - pts[c].x
	dy2 := pts[q].y - pts[c].y
	u1 := dy1 > 0 || (dy1 == 0 && dx1 > 0)
	u2 := dy2 > 0 || (dy2 == 0 && dx2 > 0)
	if u1 != u2 {
		return u1
	}
	return dx1*dy2-dy1*dx2 > 0
}

func main() {
	in := bufio.NewReaderSize(os.Stdin, 1<<20)
	out := bufio.NewWriterSize(os.Stdout, 1<<20)
	defer out.Flush()

	var N, K int
	fmt.Fscan(in, &N, &K)
	pts := make([]Pt, N)
	for i := 0; i < N; i++ {
		fmt.Fscan(in, &pts[i].x, &pts[i].y)
	}

	W := (N + 63) >> 6
	leftBits := make([]uint64, N*N*W)
	for i := 0; i < N; i++ {
		pi := pts[i]
		for j := 0; j < N; j++ {
			if i == j {
				continue
			}
			pj := pts[j]
			base := (i*N + j) * W
			for k := 0; k < N; k++ {
				pk := pts[k]
				if (pj.x-pi.x)*(pk.y-pi.y)-(pj.y-pi.y)*(pk.x-pi.x) > 0 {
					leftBits[base+(k>>6)] |= uint64(1) << uint(k&63)
				}
			}
		}
	}

	L := N - 1
	order := make([]int, N*L)
	pos := make([]int, N*N)
	for i := range pos {
		pos[i] = -1
	}
	endPos := make([]int, N*L)
	tmp := make([]int, L)
	for c := 0; c < N; c++ {
		idx := 0
		for p := 0; p < N; p++ {
			if p != c {
				tmp[idx] = p
				idx++
			}
		}
		ids := tmp[:L]
		sort.Slice(ids, func(i, j int) bool {
			return lessAround(pts, c, ids[i], ids[j])
		})
		base := c * L
		copy(order[base:base+L], ids)
		for i, p := range ids {
			pos[c*N+p] = i
		}
		r := 0
		for l := 0; l < L; l++ {
			if r < l {
				r = l
			}
			bp := ids[l]
			for r+1 < l+L && cross(pts[c], pts[bp], pts[ids[(r+1)%L]]) > 0 {
				r++
			}
			endPos[base+l] = r
		}
	}

	ans2 := int64(0)
	vals := make([]int64, 2*L)
	bestPos := make([]int64, L)
	deque := make([]int, 2*L)
	idsBuf := make([]int, L)

	for a := 0; a < N; a++ {
		pa := pts[a]
		baseOrd := a * L
		m := 0
		for t := 0; t < L; t++ {
			p := order[baseOrd+t]
			pp := pts[p]
			if pp.y > pa.y || (pp.y == pa.y && pp.x > pa.x) {
				idsBuf[m] = p
				m++
			} else {
				break
			}
		}
		if m < K-1 {
			continue
		}
		ids := idsBuf[:m]
		mm := m * m
		areaLocal := make([]int64, mm)
		triEmpty := make([]bool, mm)
		for i := 0; i < m; i++ {
			b := ids[i]
			baseAB := (a*N + b) * W
			for j := i + 1; j < m; j++ {
				c := ids[j]
				idx := i*m + j
				areaLocal[idx] = cross(pa, pts[b], pts[c])
				baseBC := (b*N + c) * W
				baseCA := (c*N + a) * W
				ok := true
				for w := 0; w < W; w++ {
					if leftBits[baseAB+w]&leftBits[baseBC+w]&leftBits[baseCA+w] != 0 {
						ok = false
						break
					}
				}
				triEmpty[idx] = ok
			}
		}

		dpPrev := make([]int64, mm)
		dpCurr := make([]int64, mm)
		for i := 0; i < mm; i++ {
			dpPrev[i] = -1
			dpCurr[i] = -1
		}

		maxLast := m - 1
		if K > 3 {
			maxLast = m - 1 - (K - 3)
		}
		for i := 0; i < maxLast; i++ {
			row := i * m
			for j := i + 1; j <= maxLast; j++ {
				idx := row + j
				if triEmpty[idx] {
					v := areaLocal[idx]
					dpPrev[idx] = v
					if K == 3 && v > ans2 {
						ans2 = v
					}
				}
			}
		}
		if K == 3 {
			continue
		}

		for length := 4; length <= K; length++ {
			for i := 0; i < mm; i++ {
				dpCurr[i] = -1
			}
			maxLast = m - 1
			if length < K {
				maxLast = m - 1 - (K - length)
			}
			iStart := length - 3
			for i := iStart; i < maxLast; i++ {
				mid := ids[i]
				for t := 0; t < L; t++ {
					vals[t] = -1
				}
				midPosBase := mid * N
				for h := 0; h < i; h++ {
					v := dpPrev[h*m+i]
					if v >= 0 {
						vals[pos[midPosBase+ids[h]]] = v
					}
				}
				for t := 0; t < L; t++ {
					vals[t+L] = vals[t]
				}

				head, tail := 0, 0
				r := 0
				epBase := mid * L
				for p := 0; p < L; p++ {
					if r < p {
						r = p
					}
					target := endPos[epBase+p]
					for r < target {
						r++
						v := vals[r]
						for head < tail && vals[deque[tail-1]] <= v {
							tail--
						}
						deque[tail] = r
						tail++
					}
					left := p + 1
					for head < tail && deque[head] < left {
						head++
					}
					if head < tail {
						bestPos[p] = vals[deque[head]]
					} else {
						bestPos[p] = -1
					}
				}

				row := i * m
				for j := i + 1; j <= maxLast; j++ {
					idx := row + j
					if !triEmpty[idx] {
						continue
					}
					best := bestPos[pos[midPosBase+ids[j]]]
					if best >= 0 {
						v := best + areaLocal[idx]
						dpCurr[idx] = v
						if length == K && v > ans2 {
							ans2 = v
						}
					}
				}
			}
			dpPrev, dpCurr = dpCurr, dpPrev
		}
	}

	fmt.Fprintf(out, "%.2f\n", float64(ans2)/2.0)
}
```