Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 38 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
38
Dung lượng
140,12 KB
Nội dung
Chuyên đề QUY HOẠCH ĐỘNG LỒI PHẦN MỞ ĐẦU Quy hoạch động (QHĐ) lớp thuật toán quan trọng có nhiều ứng dụng ngành khoa học máy tính Trong thi Olympic tin học đại, QHĐ ln chủ đề Việc áp dụng quy hoạch động vào giải tập tin học không đơn giản học sinh Nhất hầu hết tập quy hoạch động nâng thêm tầm cao Điều thể rõ đề thi VOI IOI Tuy vậy, tài liệu nâng cao QHĐ tiếng Việt khan hiếm, dẫn đến học sinhViệt Nam bị hạn chế khả tiếp cận với kỹ thuật đại Trong vài kỹ thuật để tối ưu hóa độ phức tạp thuật toán QHĐ Kỹ thuật bao lồi (convex hull trick) dùng để tối ưu hóa thuật tốn quy hoạch động với thời gian O(n2) xuống O(nlogn), chí với số trường hợp xuống O(n), cho lớp toán Code Test tập chun đề Thầy tham khảo theo đường dẫn sau: https://app.box.com/s/n2m81i1l7ic9pcfggh26onokp5hqqiiv PHẦN NỘI DUNG CHUYÊN ĐỀ I Lý thuyết Quy hoạch động bao lồi lớp thuật toán quy hoạch động Vấn đề bao gồm trì, tức theo dõi bao lồi liệu đầu vào thay đổi động, tức yếu tố liệu đầu vào chèn, xóa sửa đổi Thuật tốn áp dụng điều kiện định đáp ứng Kĩ thuật bao lồi kĩ thuật (hoặc cấu trúc liệu) dùng để xác định hiệu quả, có tiền xử lý, cực trị tập hàm tuyến tính giá trị biến độc lập Mặc dù tên gọi giống kĩ thuật lại khác biệt so với thuật tốn bao lồi hình học tính tốn Bài toán mở đầu: Cho tập N hàm bậc y=ai∗x+bi Q truy vấn, truy vấn số thực x, cần trả số thực y giá trị nhỏ hàm số với biến số x Ví dụ, cho phương trình y=4, y=4/3+2/3x, y=12−3x y=3−1/2 x truy vấn x=1 Chúng ta phải tìm phương trình mà trả giá trị y cực tiểu với x = (trong trường hợp phương trình y=4/3+2/3x giá trị cực tiểu 2) Sau ta vẽ đường thẳng lên hệ trục tọa độ, dễ thấy rằng: muốn xác định, x=1(đường màu đỏ) đường có tọa độ y nhỏ Ở trường hợp đường nét đứt đậm y=4/3+2/3x Thuật toán đơn giản Với truy vấn, ta duyệt qua tất hàm số đê tìm giá trị nhỏ Nếu có M đường thẳng Q truy vấn, độ phức tạp thuật toán O(MQ) Kĩ thuật bao lồi giúp giảm độ phức tạp xuống O((Q+M)logM, độ phức tạp hiệu nhiều Convex hull trick Mỗi hàm số bậc biểu diễn đường thẳng hệ tọa độ Oxy Xét hình vẽ Đường thẳng y=4sẽ không giá trị nhỏ với tất giá trị x Mỗi đường đường thẳng lại lại trả lại giá trị cực tiểu đoạn liên tiếp (có thể có biên +∞ −∞) Đường chấm đậm cho giá trị cực tiểu với tất giá trị x nằm bên trái giao điểm với đường đen đậm Đường đen đậm cho giá trị cực tiểu với tất giá trị giao điểm với đường nhạt đường chấm đậm Và đường nhạt nhận cực tiểu cho tất giá trị x bên phải giao điểm với đường đậm Một nhận xét với giá trị x tăng hệ số góc hàm số giảm, 2/3,−1/2,−3 Điều giúp hiểu phần thuật toán: Bỏ đường thẳng không quan trọng y=4 ví dụ (những đường thẳng mà khơng nhận giá trị cực tiểu đoạn nào) Sắp xếp đoạn thẳng lại theo hệ số góc tập N đoạn thẳng ( N số đường thẳng lại) Nếu xác định điểm cuối đoạn ta dùng thuật tốn tìm kiếm nhị phân để tìm kiếm đáp án cho truy vấn Ý nghĩa tên Cụm từ bao lồi sử dụng để hình bao trên/dưới (upper / lower envelope) Trong ví dụ, coi phần đoạn thẳng tối ưu đường thẳng (bỏ qua đường y=4), thấy đoạn tạo thành hình bao (lower envelope), tập đoạn thẳng chứa tất điểm cực tiểu cho giá trị x hình bao tơ màu xanh hình Cái tên kĩ thuật bao lồi xuất phát từ việc đường bao tạo thành đường lồi, từ thành bao lồi tập điểm Thêm đường thẳng Như nói trên, đường thẳng tiềm lọc xếp theo hệ số góc, ta dễ dàng trả lời truy vấn O(logN) sử dụng tìm kiếm nhị phân Dưới ta xét thuật tốn, ta thêm đường thẳng vào cấu trúc liệu rỗng, tính lại đường thẳng tiềm năng, cuối tất đường thẳng thêm vào cấu trúc liệu hoàn chỉnh Giả sử ta xếp tất đường thẳng giảm dần theo hệ số góc, việc lại lọc đường thẳng tiềm Khi thêm đường thẳng mới, số đường thẳng bỏ mà chúng khơng tiềm Ta sử dụng stack để chứa đường thẳng tiềm năng, đường thẳng vừa thêm vào nằm đỉnh stack Khi thêm đường thẳng mới, ta kiểm tra xem đường thẳng nằm đỉnh stack có tiềm hay khơng Nếu tiềm năng, ta việc đẩy thêm đường thẳng vào tiếp tục Nếu khơng, ta bỏ lại tiếp tục lại trình đường thẳng đỉnh stack tiềm stack đường thẳng Vấn đề lại để kiểm tra xem đường thẳng bỏ hay không Gọi l1, l2, l3 đường thẳng thứ hai, thứ (ở đỉnh stack),và đường thẳng để thêm vào Thì l2 trở nên không tiềm điểm cắt l1 l3 nằm bên trái (có hồnh độ nhỏ hơn) điểm cắt l1 l2 Điều xảy l3 phủ hết khoảng mà trước l2là thấp Thuật tốn tập đường thẳng đôi không song song, khơng ta việc sửa đổi thuật tốn xếp để đường thẳng tiềm (có số nhỏ hơn) sau đường thẳng song song với Đánh giá độ phức tạp Về mặt nhớ, độ phức tạp thuật toán O(M), mà ta cần lưu trữ danh sách đường thẳng xếp Bước xếp ban đầu làm O(MlogM) Khi duyệt qua đường thẳng, chúng đẩy vào stack lần, bị pop khơng q lần Như bước dựng bao lồi thời gian O(M) Tóm lại tồn thuật tốn bao gồm phần xếp thời gian O(MlogM), đường thẳng xếp sẵn, thuật tốn chạy thời gian tuyến tính II BÀI TẬP ÁP DỤNG Bài 1.HARBINGERS (CEOI 2009) Ngày xửa ngày xưa, có N thị trấn kiểu trung cổ khu tự trị Moldavian Các thị trấn đánh số từ đến N Thị trấn 1là thủ đô Các thị trấn nối với N−1 đường hai chiều, đường có độ dài đo km Có tuyến đường nối hai thị trấn (đồ thị đường hình cây) Mỗi thị trấn khơng phải trung tâm có người truyền tin Khi thị trấn bị cơng, tình hình chiến phải báo cáo sớm tốt cho thủ đô Mọi thông điệp truyền người truyền tin Mỗi người truyền tin đặc trưng lượng thời gian khởi động vận tốc không đổi sau xuất phát Thông điệp truyền đường ngắn đến thủ đô Ban đầu, thông tin chiến đưa cho người truyền tin thị trấn bị công Trong thị trấn mà qua, người truyền tin có hai lựa chọn: đến thị trấn phía thủ đơ, để lại tin nhắn đến người truyền tin từ thị trấn Người truyền tin lại áp dụng tương tự cách Nói chung thơng điệp thực số người truyền tin trước đến thủ đô Nhiệm vụ bạn thị trấn tìm thời gian tối thiểu để gửi tin nhắn từ thị trấn đến thủ Input: file harbingers.inp harbingers.inp harbingers.out Dòng đầu ghi số N 206 321 542 328 N−1dòng tiếp theo, dòng ghi ba số u, v, d thể đường 20 12 nối từ u đến v với độ dài d N−1 dòng tiếp theo, dòng thứ i gồm hai số Si Vi mô tả đặc điểm người truyền tin thị trấn thứ i+1 26 Si thể thời gian cần để khởi 10 động Vi số lượng phút để 500 1km người truyền tin thị 30 trấn i+1 Output: file harbingers.out Ghi N−1 số dòng Số thứ iithể thời gian cần truyền tin từ thành phố i+1 thủ Ví dụ Giới hạn 3≤N≤100 000 0≤Si≤109 1≤Vi≤109 Độ dài đường không vượt 10 000 Ràng buộc 20% số test, N ≤ 500 50% số test, thị trấn có nhiều đường liền kề Giải thích Các đường độ dài chúng hiển thị hình bên trái Thời gian khởi động tốc độ người đưa tin viết dấu ngoặc Thời gian tối thiểu để gửi tin nhắn từ thị trấn đến thủ đô đạt sau Người báo hiệu từ thị trấn nhận thông điệp rời khỏi thị trấn sau phút Anh km 120 vài phút trước đến thị trấn Anh ta để lại tin nhắn từ thị trấn Tin nhắn thứ hai cần 26 phút để bắt đầu hành trình 180 phút đến thủ đô Tổng thời gian là: + 120 + 26 + 180 = 328 Phân tích Thuật toán QHĐ Subtask1 Cách tiếp cận sử dụng lập trình động Nếu chúng tơi coi opti thời gian tối thiểu cần thiết để gửi tin nhắn từ thị trấn i đến thủ đơ, chúng tơi có cơng thức đệ quy sau: Opti = (optj + distj-> i ∙ Vi + Si) (1) Trong j nút đường dẫn từ thị trấn i đến thị trấn Mối quan hệ có cách xem xét người đưa tin j nhận thơng báo từ người đưa tin i dist j-> i biểu thị khoảng cách nút j i Khoảng cách tính thời gian khơng đổi ban đầu tính vectơ D, Di khoảng cách từ thị trấn i đến thủ đô Việc thực trực tiếp (1) thời gian O (N2) Subtask Cơng thức (1) viết lại thành: Opti = (optj – Dj • Vi + Di • Vi + Si) (2) Khi tính tốn giá trị cho opti, Di • Vi + Si số cho tất j, vậy: Opti = (optj – Dj • Vi ) + Di • Vi + Si (3) Chúng ta cần tìm tối thiểu cho biểu thức opt j – Dj • Vi Điều có giải thích hình học hữu ích: nút i, coi đường thẳng mặt phẳng cho phương trình Y = opti – Di • X Tìm giá trị tối thiểu tương đương với: tìm đường thấp mặt phẳng cắt đường X = V i Để giải truy vấn cách hiệu quả, trì đường bao thấp đường thẳng Bởi độ dài đường dương, có D j = (double)(c.Y - a.Y) / (a.X - c.X);} long long getMin(long long coord) { int l = 0, r = top - 1; long long ans = eval(lines[l], coord); while (l < r) { int mid = l + r >> 1; long long x = eval(lines[mid], coord); long long y = eval(lines[mid + 1], coord); if (x > y) l = mid + 1; else r = mid; ans = min(ans, min(x, y)); } return ans; } bool insertLine(Line newLine) { int l = 1, r = top - 1, k = top; while (l > 1; if (bad(lines[mid - 1], lines[mid], newLine)) { k = mid; r = mid - 1; } else l = mid + 1; } undoLst.push_back(operation(k, top, lines[k])); top = k + 1; lines[k] = newLine; return 1; } void undo() { operation ope = undoLst.back(); undoLst.pop_back(); top = ope.top; lines[ope.pos] = ope.overwrite; } long long f[N], S[N], V[N], d[N]; vector a[N]; void dfs(int u, int par) { if (u > 1) f[u] = getMin(V[u]) + S[u] + V[u] * d[u]; insertLine(make_pair(-d[u], f[u])); for (vector::iterator it = a[u].begin(); it != a[u].end(); ++it) { int v = it->X; int uv = it->Y; if (v == par) continue; d[v] = d[u] + uv; dfs(v, u); } undo(); } int main() { ios::sync_with_stdio(0); cin.tie(0); cin >> n; int u, v, c; for (int i = 1; i < n; ++i) { cin >> u >> v >> c; a[u].push_back(make_pair(v, c)); a[v].push_back(make_pair(u, c)); } for (int i = 2; i > S[i] >> V[i]; dfs(1, 0); for (int i = 2; i