trang chủ / bài tập / greenhouse / lời giải

Nhà kính của Sprout

Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Tác giả: huunguyenhuunguyen

Hướng tiếp cận

Bài toán tương đương với bài toán Post Office kinh điển: đặt K cơ sở trên đường thẳng để tối thiểu tổng khoảng cách tuyệt đối từ N điểm đến cơ sở gần nhất.

Ta giải bằng quy hoạch động kết hợp tối ưu chia để trị (Divide and Conquer Optimization).

Nhận xét quan trọng

  1. Sắp xếp: Sau khi sắp xếp các vị trí cây, phân hoạch tối ưu luôn chia thành K đoạn con liên tiếp - mỗi đoạn được phục vụ bởi một nhà kính.

  2. Vị trí tối ưu cho một đoạn: Với đoạn cây [l,r], nhà kính tối ưu nằm tại trung vị xm (với m=(l+r)/2), cho chi phí i=lr|xixm|.

  3. Tính nhanh chi phí đoạn: Dùng mảng tổng tiền tố (prefix sum), ta tính chi phí đoạn [l,r] trong O(1): cost(l,r)=(ml)·xm(SmSl)+(Sr+1Sm+1)(rm)·xm trong đó Si=x0+x1++xi1.

  4. Bất đẳng thức tứ giác: Hàm cost(l,r) thỏa mãn bất đẳng thức tứ giác (quadrangle inequality), tức là: cost(a,c)+cost(b,d)cost(a,d)+cost(b,c)abcd Điều này cho phép áp dụng tối ưu chia để trị trên DP.

Thuật toán

  1. Sắp xếp các vị trí x1,,xN.

  2. Xây dựng mảng tổng tiền tố S.

  3. DP cơ sở (k=1): dp[i]=cost(0,i1) cho mọi i.

  4. DP lặp cho k=2,3,,K: dpk[i]=minj<i(dpk1[j]+cost(j,i1))

    Gọi opt(i) là giá trị j tối ưu cho dpk[i]. Nhờ bất đẳng thức tứ giác, ta có opt(i)opt(i+1). Điều này cho phép dùng chia để trị:

    • Với đoạn [lo,hi], tính dpk[mid] bằng cách duyệt j[opt\_lo,opt\_hi].
    • Tìm opt(mid), sau đó đệ quy:
      • Nửa trái [lo,mid1] với opt[opt\_lo,opt(mid)]
      • Nửa phải [mid+1,hi] với opt[opt(mid),opt\_hi]
  5. Kết quả: dpK[N].

Độ phức tạp

  • Thời gian: O(NlogN+N·K·logN). Sắp xếp O(NlogN), mỗi vòng DP tốn O(NlogN) nhờ chia để trị, lặp K vòng.
  • Bộ nhớ: O(N) - chỉ cần lưu hai hàng DP.

Bình luận

Không có bình luận tại thời điểm này.

gnatmake 12.2.0 a68g 3.1.2 nasm 2.16.1 as_x64 2.46 awk 1.3.4 gcc 16.1.0 csc 6.12.0.200 g++ 16.1.0 g++-themis 16.1.0 g++17 16.1.0 g++20 16.1.0 g++23 16.1.0 clang++ 22.1.6 dmd 2.112.0 dart 3.12.1 gforth 0.7.3 gfortran 12.2.0 go 1.26.3 groovyc 5.0.6 javac 25.0.3 node 26.2.0 kotlinc 2.3.21 sbcl 2.2.9 lua 5.4.8 nim 2.2.10 fpc 3.2.2 fpc-themis 3.2.2 perl 5.36.0 php 8.5.6 pike 8.0 pypy3 7.3.23 python3 3.14.5 racket 8.7 ruby 4.0.5 rustc 1.96.0 csc 5.3.0 ctoj-scratch 0.0.1 sed 4.9 tclsh 8.6 bun 1.3.14 deno 2.8.1 v 0.5.1 zig 0.16.0