| # | Bài tập | Điểm | Thời gian: | Giới hạn bộ nhớ |
|---|---|---|---|---|
| 1 | JOI 2016 - Dangerous Skating | 100 (p) | 3.0s | 256M |
| 2 | JOI 2016 - Snowy Roads | 100 (p) | 1.0s | 256M |
| 3 | JOI 2016 - Worst Reporter 2 | 100 (p) | 2.0s | 256M |
JOI thích trượt băng trên một sân băng rộng lớn giữa thiên nhiên.
Sân băng được biểu diễn bằng một hình chữ nhật gồm \(R\) hàng theo hướng bắc–nam và \(C\) cột theo hướng đông–tây. Gọi ô ở hàng thứ \(r\) tính từ phía bắc, cột thứ \(c\) tính từ phía tây là ô \((r,c)\). Mỗi ô hoặc có thể đi qua, hoặc chứa một khối băng và không thể đi qua. Tất cả các ô trên biên sân đều chứa khối băng, nên JOI không thể trượt ra ngoài sân. Cụ thể, các ô \((i,1)\), \((i,C)\) với \(1 \le i \le R\) và các ô \((1,j)\), \((R,j)\) với \(1 \le j \le C\) đều chứa khối băng.
JOI trượt băng không giỏi lắm. Mỗi lần di chuyển, cậu đạp vào ô đang đứng để trượt theo một trong bốn hướng đông, tây, nam, bắc và chỉ dừng lại ở ô ngay trước khối băng đầu tiên gặp phải. Quá trình từ lúc đạp vào mặt sân đến lúc dừng lại được tính là một lần di chuyển. Nếu ô liền kề theo một hướng chứa khối băng, cậu không thể di chuyển theo hướng đó.
Một hôm, khi đang trượt băng, JOI phát hiện rằng mỗi khi cậu đạp vào mặt sân, một khối băng sẽ mọc lên tại chính ô đó. Các ô cậu trượt qua, ngoại trừ ô đạp chân để bắt đầu di chuyển, không xuất hiện khối băng. Tiếp tục trượt trong tình trạng này rất nguy hiểm, nên JOI muốn thoát khỏi sân băng càng nhanh càng tốt.
Hiện tại JOI đang ở ô \((r_1,c_1)\). Để thoát khỏi sân băng, cậu phải dừng lại tại ô lối ra \((r_2,c_2)\). Chỉ trượt ngang qua ô lối ra trong một lần di chuyển là chưa đủ để thoát. Tùy trạng thái sân và vị trí ban đầu, có thể không có cách nào để cậu dừng tại lối ra.
Cho vị trí các khối băng, vị trí hiện tại của JOI và vị trí lối ra. Hãy xác định JOI có thể bắt đầu từ vị trí hiện tại và dừng tại lối ra hay không; nếu có, tìm số lần di chuyển ít nhất cần thực hiện.
Đọc từ đầu vào chuẩn:
. hoặc #. Ký tự thứ \(c\) trên dòng thứ \(r\) trong số này mô tả trạng thái ban đầu của ô \((r,c)\): . là ô có thể đi qua, còn # là ô chứa khối băng và không thể đi qua.In ra đầu ra chuẩn một số nguyên trên một dòng: số lần di chuyển ít nhất để JOI dừng tại ô lối ra. Nếu không thể dừng tại ô lối ra bằng bất kỳ cách di chuyển nào, in -1.
Ví dụ 1
5 5
#####
#...#
#...#
#...#
#####
2 2
3 3
4
Trạng thái ban đầu của sân băng như hình dưới đây. Ô có hình vuông trắng chứa khối băng, J là vị trí hiện tại của JOI, còn E là lối ra.
Trước hết, JOI di chuyển về phía đông. Sân băng trở thành:
Sau đó, JOI lần lượt di chuyển về phía tây, phía nam, rồi phía bắc để dừng tại lối ra sau tổng cộng \(4\) lần di chuyển. Không thể dừng tại lối ra sau \(3\) lần di chuyển hoặc ít hơn, nên đáp án là 4.
Ví dụ 2
8 6
######
#..#.#
##...#
#....#
#.#..#
#....#
##...#
######
4 3
6 4
5
Ví dụ 3
5 5
#####
#.#.#
#.#.#
#.#.#
#####
2 2
4 4
-1
Ví dụ 4
3 3
###
#.#
###
2 2
2 2
0
Trong ví dụ này, JOI đang đứng ngay tại ô lối ra, nên số lần di chuyển cần thiết là \(0\).
Vào mùa đông, nhiều nơi ở Nga có tuyết rơi. Nước Nga có \(N\) thành phố, được đánh số từ \(0\) đến \(N-1\), và \(N-1\) con đường, được đánh số từ \(0\) đến \(N-2\). Đường \(i\) nối hai chiều giữa hai thành phố khác nhau \(A_i\) và \(B_i\), trong đó \(0 \le A_i < B_i \le N-1\). Có thể đi lại giữa bất kỳ hai thành phố khác nhau nào qua một số con đường.
Tình trạng tuyết rơi trên mỗi con đường thay đổi theo ngày. Vào mỗi ngày, một con đường hoặc có tuyết rơi, hoặc không có tuyết rơi; tình trạng này không thay đổi trong ngày.
Anya và Boris làm việc tại cơ quan giao thông của Nga. Anya thuộc bộ phận quản lý thông tin đường sá, còn Boris thuộc bộ phận trả lời câu hỏi của người dân. Người dân muốn biết số con đường có tuyết rơi ít nhất phải đi qua để từ thủ đô, tức thành phố \(0\), đến một thành phố khác. Thông thường, sau khi nhận câu hỏi, Boris trao đổi với Anya rồi trả lời người dân.
Sắp tới, Nga sẽ tổ chức một cuộc thi lập trình thế giới kéo dài \(Q\) ngày. Trong thời gian này, đường truyền dự kiến sẽ bị quá tải, khiến Anya và Boris khó trao đổi trực tiếp. Vì vậy, họ quyết định liên lạc theo cách sau:
Việc liên lạc phải tuân theo các giới hạn sau:
Bạn là người quen của giám đốc cơ quan giao thông và được nhờ xây dựng chiến lược cho Anya và Boris.
Trong hình, các nhãn tiếng Nhật lần lượt có nghĩa là “Thông tin tuyết rơi” ở phía dưới Anya, “Máy chủ trung gian” và “Dung lượng \(L\) bit” ở giữa, “Tối đa \(20\) bit cho mỗi câu hỏi” trên đường nối tới Boris, và “Người dân” ở phía dưới Boris.
Hãy viết chương trình cài đặt chiến lược của Anya và Boris để trả lời đúng các câu hỏi của người dân.
Nộp một tệp mã nguồn C++ include snowy.h được đính kèm theo bài và cài đặt cả bốn hàm dưới đây. Hệ thống chấm biên dịch cùng một mã nguồn cho hai tiến trình riêng biệt: một tiến trình thực hiện vai trò Anya và tiến trình còn lại thực hiện vai trò Boris.
Hai hàm sau cài đặt chiến lược của Anya.
void InitAnya(int N, int A[], int B[]);
Hàm này được gọi đúng một lần trong mỗi bộ kiểm thử.
N là số thành phố.A[] và B[] đều là mảng có độ dài \(N-1\), mô tả các con đường. Với \(0 \le i \le N-2\), đường \(i\) nối hai chiều giữa thành phố A[i] và B[i], thỏa mãn \(0 \le A[i] < B[i] \le N-1\).void Anya(int C[]);
Hàm này được gọi \(Q\) lần sau khi InitAnya được gọi. Mỗi lần gọi tương ứng với việc Anya quyết định dãy bit cần lưu lên máy chủ sau khi thông tin tuyết rơi được cập nhật vào đầu ngày.
C[] là mảng có độ dài \(N-1\), mô tả tình trạng tuyết rơi. Với \(0 \le i \le N-2\), C[i] là \(0\) hoặc \(1\): C[i] = 1 nghĩa là đường \(i\) có tuyết rơi; C[i] = 0 nghĩa là đường đó không có tuyết rơi.Trong hàm Anya, bạn có thể gọi hàm sau:
void Save(int place, int bit);
Hàm này biểu diễn thao tác Anya lưu một bit lên máy chủ.
place là vị trí cần ghi, phải là một số nguyên từ \(0\) đến \(L-1\). Nếu nằm ngoài khoảng này, chương trình bị chấm Wrong Answer [1].Anya, không được gọi Save hai lần hoặc nhiều hơn với cùng một giá trị place. Nếu ghi cùng vị trí lần thứ hai, chương trình bị chấm Wrong Answer [2].bit là giá trị cần ghi, phải là \(0\) hoặc \(1\). Giá trị khác sẽ bị chấm Wrong Answer [3].Sau khi gọi Save, bit tại vị trí place trên máy chủ có giá trị bit. Nếu một lần gọi Save bị chấm sai, chương trình kết thúc ngay.
Ngay trước mỗi lần gọi Anya, toàn bộ bit trên máy chủ luôn được khởi tạo lại thành \(0\). Vì thế, khi Anya kết thúc, các vị trí không được ghi bằng Save vẫn có giá trị \(0\).
Hai hàm sau cài đặt chiến lược của Boris.
void InitBoris(int N, int A[], int B[]);
Hàm này được gọi đúng một lần trong mỗi bộ kiểm thử.
N là số thành phố.A[] và B[] đều là mảng có độ dài \(N-1\), mô tả các con đường. Với \(0 \le i \le N-2\), đường \(i\) nối hai chiều giữa thành phố A[i] và B[i], thỏa mãn \(0 \le A[i] < B[i] \le N-1\).int Boris(int city);
Hàm này được gọi một số lần sau khi InitBoris được gọi. Mỗi lần gọi tương ứng với việc Boris trả lời một câu hỏi của người dân.
city là một số nguyên từ \(1\) đến \(N-1\), biểu thị câu hỏi: để đi từ thành phố \(0\) đến thành phố city, cần đi qua ít nhất bao nhiêu con đường có tuyết rơi?Wrong Answer [4]. Nếu câu trả lời không đúng, chương trình bị chấm Wrong Answer [7].Trong hàm Boris, bạn có thể gọi hàm sau:
int Ask(int place);
Hàm này biểu diễn thao tác Boris đọc một bit từ máy chủ.
place là vị trí cần đọc, phải là một số nguyên từ \(0\) đến \(L-1\). Nếu nằm ngoài khoảng này, chương trình bị chấm Wrong Answer [5].place trên máy chủ, là \(0\) hoặc \(1\).Boris, chỉ được gọi Ask tối đa \(20\) lần. Nếu gọi quá \(20\) lần, chương trình bị chấm Wrong Answer [6].Nếu một lần gọi Ask bị chấm sai, chương trình kết thúc ngay.
Chương trình được chấm theo trình tự sau. Nếu bị chấm sai ở bất kỳ thời điểm nào, chương trình kết thúc ngay.
InitAnya một lần, rồi gọi InitBoris một lần, theo đúng thứ tự đó, để cung cấp thông tin các con đường.Anya đúng một lần. Lần gọi này tương ứng với việc Anya quyết định dãy bit cần lưu lên máy chủ sau khi thông tin tuyết rơi được cập nhật vào đầu ngày.Boris \(D_i\) lần, trong đó \(D_i\) là số câu hỏi của người dân trong ngày thứ \(i\). Lần gọi thứ \(j\), với \(1 \le j \le D_i\), nhận đối số \(R_{ij}\), thỏa mãn \(1 \le R_{ij} \le N-1\). Nếu giá trị trả về không bằng số con đường có tuyết rơi ít nhất phải đi qua để từ thành phố \(0\) đến thành phố \(R_{ij}\), chương trình bị chấm sai.Anya được gọi tổng cộng \(Q\) lần và Boris được gọi tổng cộng \(D_1+\cdots+D_Q\) lần.Boris không được cung cấp thông tin cho biết thời điểm Anya cập nhật dữ liệu trên máy chủ.Không viết hàm main, không đọc đầu vào chuẩn và không ghi đầu ra chuẩn. Hệ thống chấm cung cấp Save cho tiến trình Anya, cung cấp Ask cho tiến trình Boris, và gọi các hàm theo đúng quy trình ở trên.
Dưới đây là một ví dụ đầu vào của chương trình chấm mẫu và một trình tự gọi hàm tương ứng.
5
0 1
1 2
1 4
2 3
2
0101 3 2 4 3
1110 1 4
Trong bảng, “không có” nghĩa là hàm không có giá trị trả về. Các thao tác trong một lần gọi được liệt kê theo thứ tự thực hiện.
| Hàm được gọi | Các lời gọi bên trong và giá trị trả về | Giá trị trả về của hàm |
|---|---|---|
InitAnya(...) |
— | Không có |
InitBoris(...) |
— | Không có |
Anya(...) lần 1 |
Save(0,1) → không có; Save(1,0) → không có; Save(500,1) → không có |
Không có |
Boris(2) |
Ask(0) → 1; Ask(1) → 0; Ask(2) → 0 |
1 |
Boris(4) |
— | 0 |
Boris(3) |
— | 2 |
Anya(...) lần 2 |
— | Không có |
Boris(4) |
Ask(0) → 0 |
2 |
Lưu ý rằng các lời gọi trong ví dụ này không nhất thiết có ý nghĩa như một chiến lược giải bài.
Các đối số truyền cho InitAnya(...), InitBoris(...) và hai lần gọi Anya(...) lần lượt là:
| Đối số | InitAnya(...) |
InitBoris(...) |
Anya(...) lần 1 |
Anya(...) lần 2 |
|---|---|---|---|---|
N |
5 |
5 |
— | — |
A |
{0, 1, 1, 2} |
{0, 1, 1, 2} |
— | — |
B |
{1, 2, 4, 3} |
{1, 2, 4, 3} |
— | — |
C |
— | — | {0, 1, 0, 1} |
{1, 1, 1, 0} |
Vào năm 21XX, lập trình thi đấu đã được công nhận rộng rãi là một môn thể thao trí tuệ và thường xuyên được đưa tin trên truyền hình, báo chí cùng các phương tiện truyền thông khác.
Bạn là phóng viên của báo JOI, phụ trách các bài viết về lập trình thi đấu.
Hôm qua, một cuộc thi lập trình quốc tế với \(N\) thí sinh đã diễn ra. Để viết bài về cuộc thi, bạn được cung cấp những thông tin sau:
Tuy nhiên, khi chuẩn bị viết bài, bạn phát hiện chức năng hiển thị quốc gia trên bảng xếp hạng đã gặp lỗi. Thông tin về quốc gia của thí sinh có thể đã bị hiển thị sai. Bạn biết chắc rằng các số điểm được hiển thị đều đúng.
Bạn quyết định sửa ít thông tin nhất có thể để thu được các bảng xếp hạng không mâu thuẫn: quốc gia của cùng một thí sinh không thay đổi trong cuộc thi và điểm của thí sinh không giảm đi. Cụ thể, bạn muốn thay đổi ít vị trí nhất trong \(2N\) giá trị \(A_1,\ldots,A_N,C_1,\ldots,C_N\) sao cho tồn tại một hoán vị \(x_1,x_2,\ldots,x_N\) của \(1,2,\ldots,N\) thỏa mãn:
Bạn cần sửa ít nhất bao nhiêu vị trí trong thông tin được cung cấp?
Cho số thí sinh và thông tin bảng xếp hạng sau \(2\) giờ cũng như khi kết thúc cuộc thi. Hãy tìm số vị trí thông tin quốc gia ít nhất cần thay đổi để các bảng xếp hạng không mâu thuẫn.
Đọc từ đầu vào chuẩn:
In ra đầu ra chuẩn một dòng chứa số vị trí thông tin quốc gia ít nhất cần thay đổi để các bảng xếp hạng không mâu thuẫn.
Ví dụ 1
3
3 500
2 200
1 100
1 1000
3 700
3 400
1
Sửa \(C_3\) thành \(2\) sẽ cho các bảng xếp hạng không mâu thuẫn:
Nếu sửa \(C_2\) thành \(2\) thì bảng xếp hạng sẽ mâu thuẫn: thí sinh đến từ quốc gia \(3\) có \(500\) điểm sau \(2\) giờ nhưng chỉ còn \(400\) điểm khi kết thúc.
Không thể thu được các bảng xếp hạng không mâu thuẫn bằng ít hơn một lần sửa, nên in 1.
Ví dụ 2
3
3 3
3 2
1 1
3 4
3 2
1 1
0
Trong trường hợp này, các bảng xếp hạng đã không mâu thuẫn nên không cần sửa thông tin quốc gia. Lưu ý rằng một thí sinh có thể không tăng điểm kể từ thời điểm sau \(2\) giờ, và nhiều thí sinh trên bảng xếp hạng có thể đến từ cùng một quốc gia.
Ví dụ 3
6
1 70
4 50
1 30
2 20
1 10
3 0
6 100
2 90
1 80
2 60
4 40
1 10
3
Trong ví dụ này, sửa \(A_1\) thành \(2\), \(A_6\) thành \(4\) và \(C_1\) thành \(4\) sẽ cho các bảng xếp hạng không mâu thuẫn.