| # | Bài tập | Điểm | Thời gian: | Giới hạn bộ nhớ |
|---|---|---|---|---|
| 1 | Google Code Jam 2016 - Freeform Factory | 31 | 1.0s | 1G |
| 2 | Google Code Jam 2016 - Rather Perplexing Showdown | 18 | 1.0s | 1G |
| 3 | Google Code Jam 2016 - Red Tape Committee | 22 | 1.0s | 1G |
| 4 | Google Code Jam 2016 - The Gardener of Seville | 29 | 1.0s | 1G |
Bạn vừa xây xong một nhà máy hoàn toàn mới. Nhà máy có \(N\) máy khác nhau, và để hoạt động tốt, mỗi máy cần được đúng một công nhân vận hành.
Bạn cũng thuê \(N\) công nhân để vận hành các máy đó. Vì tuyển người quá gấp, bạn chưa kiểm tra xem họ có thật sự biết dùng máy hay không. Giờ bạn đã hỏi và biết, với mọi \(i,j\), công nhân thứ \(i\) có biết vận hành máy thứ \(j\) hay không.
Trong một ngày làm việc thông thường, công nhân đến nhà máy theo thứ tự ngẫu nhiên và thứ tự có thể khác mỗi ngày. Khi một người tới, họ tìm tất cả máy mà mình biết vận hành và chưa có người vận hành, rồi chọn ngẫu nhiên một máy trong số đó và làm việc với máy ấy suốt ngày. Nếu mọi máy họ biết vận hành đều đã có người, hôm đó họ sẽ không làm việc. Mục tiêu của bạn là bảo đảm mọi máy đều được vận hành mỗi ngày, bất kể công nhân đến theo thứ tự nào và chọn máy nào.
Ví dụ, có hai công nhân A, B và hai máy 1, 2. A biết vận hành cả 1 và 2; B biết vận hành 1 nhưng không biết 2. Nếu B đến trước, B chọn máy 1, rồi A buộc phải chọn máy 2 và nhà máy hoạt động tốt. Nhưng nếu A đến trước, A có thể chọn máy 1; khi B tới sẽ không còn việc, máy 2 không có người vận hành và nhà máy lãng phí cả ngày!
Ví dụ khác, vẫn có A, B và máy 1, 2, nhưng A chỉ biết máy 1 còn B không biết vận hành máy nào. Dù công nhân đến theo thứ tự nào, nhà máy cũng không thể hoạt động tốt.
Trước khi mở nhà máy, để bảo đảm nhà máy luôn hoạt động tốt, bạn có thể dạy công nhân vận hành thêm máy. Mỗi bài học dạy một công nhân vận hành một máy có giá một đô-la. Mỗi bài học chỉ liên quan đến một công nhân và một máy, nhưng bạn có thể dạy bao nhiêu bài cho bao nhiêu người tùy ý, và một người có thể học nhiều bài. Bạn không thể làm một công nhân quên cách vận hành máy họ đã biết.
Cả hai ví dụ trên đều có thể sửa bằng cách dạy B vận hành máy 2. Khi đó, mọi máy chắc chắn có người mỗi ngày, bất kể thứ tự đến và lựa chọn của công nhân khi họ có nhiều phương án.
Số đô-la tối thiểu cần chi cho đào tạo để bảo đảm nhà máy hoạt động tốt mỗi ngày là bao nhiêu?
Dòng đầu tiên chứa số bộ test \(T\). Mỗi bộ test bắt đầu bằng một dòng chứa số nguyên \(N\), là số công nhân (và cũng là số máy). Tiếp theo là \(N\) dòng, mỗi dòng là chuỗi \(N\) ký tự. Ký tự thứ \(j\) của dòng thứ \(i\) là 1 nếu công nhân \(i\) biết vận hành máy \(j\), và là 0 nếu không.
Với mỗi bộ test, in một dòng Case #x: y, trong đó x là số thứ tự bộ test (bắt đầu từ 1), còn y là số nguyên không âm: số đô-la tối thiểu cần chi để chắc chắn cả \(N\) máy luôn có người vận hành.
Mỗi Test Set tương ứng với một subtask trên LQDOJ. Bảng dưới đây giữ nguyên điểm chính thức của Google Code Jam và quy đổi tỷ lệ trên tổng điểm của bài.
| Phân nhóm | Điểm Google Code Jam | Tỷ lệ điểm của bài |
|---|---|---|
| Test Set 1 | 6/31 | 19,35% |
| Test Set 2 | 25/31 | 80,65% |
Ví dụ 1
5
2
11
10
2
10
00
3
000
000
000
1
1
3
000
110
000
Case #1: 1
Case #2: 1
Case #3: 3
Case #4: 0
Case #5: 3
Bộ test mẫu số 1 và 2 chính là hai ví dụ trong đề bài.
Trong bộ test số 3, không ai biết làm gì! Một chiến lược tối ưu là dạy A vận hành máy 1, B vận hành máy 2 và C vận hành máy 3.
Trong bộ test số 4, không cần làm gì: chỉ có một công nhân và người đó đã biết vận hành máy duy nhất.
Trong bộ test số 5, B đã biết máy 1 và 2. Một chiến lược tối ưu là dạy A vận hành máy 3 và để A là người duy nhất biết máy ấy. Nhưng B có thể chọn máy 1 hoặc 2 khi tới, nên C phải vận hành được máy B không chọn. Vì vậy, cần dạy C cả máy 1 lẫn máy 2.
Google Code Jam 2016, Vòng 2, bài Freeform Factory.
Nguồn chính thức trên Google Coding Competitions Archive, phát hành theo giấy phép Apache-2.0.
Bạn được giao tổ chức một giải Oẳn tù tì. Giải đấu theo thể thức loại trực tiếp, kéo dài \(N\) vòng và có \(2^N\) người tham gia.
Ban đầu, các đấu thủ xếp thành hàng từ trái sang phải theo thứ tự do bạn chọn. Trong mỗi vòng, người thứ nhất đấu người thứ hai, người thứ ba đấu người thứ tư nếu có, và cứ như vậy; mọi trận diễn ra đồng thời. Người thắng ở lại hàng theo đúng thứ tự tương đối cũ, người thua rời hàng và về nhà. Sau đó vòng mới bắt đầu. Quá trình tiếp tục tới khi chỉ còn một người, và người đó là nhà vô địch.
Trong mỗi trận Oẳn tù tì, hai người bí mật chọn một trong Búa, Bao hoặc Kéo, rồi so sánh. Búa thắng Kéo, Kéo thắng Bao, Bao thắng Búa. Nếu lựa chọn của một người thắng lựa chọn của người kia, người đó thắng và trận kết thúc. Nhưng nếu hai người chọn giống nhau thì hòa; họ phải chọn lại và tiếp tục chơi cho tới khi có người thắng.
Bạn biết các đấu thủ năm nay rất bướng bỉnh và không mấy chiến thuật. Mỗi người có một lựa chọn ưa thích và chỉ dùng đúng lựa chọn ấy trong mọi trận, bất kể đối thủ làm gì. Vì vậy, nếu hai người có cùng lựa chọn gặp nhau, họ sẽ hòa mãi và trận đấu kéo dài vô tận! Nếu điều này xảy ra, giải sẽ không bao giờ kết thúc và bạn sẽ trở thành trò cười.
Năm nay có \(R\) người thích Búa, \(P\) người thích Bao và \(S\) người thích Kéo. Bạn muốn tạo một hàng đấu thủ bảo đảm giải kết thúc và có đúng một người thắng, tức không trận nào từng hòa. Sếp yêu cầu bạn lập danh sách mọi hàng hợp lệ, viết từ trái sang phải bằng R, P, S tương ứng với Búa, Bao, Kéo, rồi sắp danh sách theo thứ tự từ điển.
Bạn biết sếp sẽ lười biếng chọn ngay hàng đầu tiên trong danh sách. Hàng đó là gì? Hay bạn phải báo IMPOSSIBLE vì không thể tránh hòa?
Dòng đầu tiên chứa số bộ test \(T\). Mỗi dòng tiếp theo là một bộ test gồm bốn số nguyên \(N,R,P,S\) như mô tả trên.
Với mỗi bộ test, in một dòng Case #x: y, trong đó x là số thứ tự bộ test (bắt đầu từ 1), còn y là IMPOSSIBLE hoặc chuỗi độ dài \(2^N\) biểu diễn hàng ban đầu nhỏ nhất theo thứ tự từ điển giải được bài toán. Mỗi ký tự phải là R, P hoặc S, và chuỗi phải chứa đúng \(R\) ký tự R, \(P\) ký tự P, \(S\) ký tự S.
Mỗi Test Set tương ứng với một subtask trên LQDOJ. Bảng dưới đây giữ nguyên điểm chính thức của Google Code Jam và quy đổi tỷ lệ trên tổng điểm của bài.
| Phân nhóm | Điểm Google Code Jam | Tỷ lệ điểm của bài |
|---|---|---|
| Test Set 1 | 4/18 | 22,22% |
| Test Set 2 | 14/18 | 77,78% |
Ví dụ 1
4
1 1 1 0
1 2 0 0
2 1 1 2
2 2 0 2
Case #1: PR
Case #2: IMPOSSIBLE
Case #3: PSRS
Case #4: IMPOSSIBLE
Trong bộ test số 1 chỉ có hai người và một vòng. Thứ tự không ảnh hưởng kết quả: người dùng Bao thắng người dùng Búa. Danh sách theo thứ tự từ điển là PR, RP, nên sếp nhận PR.
Trong bộ test số 2, cả hai người đều dùng Búa nên không thể tránh hòa.
Trong bộ test số 3 có bốn người và hai vòng. Vòng đầu, người thứ nhất (Bao) thua người thứ hai (Kéo), còn người thứ ba (Búa) thắng người thứ tư (Kéo). Hàng vòng hai là PR; người đầu còn lại (Bao) thắng người kia (Búa), nên giải kết thúc không hòa.
Hình sau minh họa giải đấu của bộ test số 3:
Các hàng khác như PSSR cũng xuất hiện trong danh sách đưa cho sếp, nhưng PSRS đứng trước theo thứ tự từ điển.
Trong bộ test số 4, cách duy nhất để vòng đầu không hòa là tạo hai trận, mỗi trận có một người Búa và một người Kéo. Cả hai trận đều có người Búa thắng; khi hai người thắng gặp nhau, họ sẽ hòa.
Google Code Jam 2016, Vòng 2, bài Rather Perplexing Showdown.
Nguồn chính thức trên Google Coding Competitions Archive, phát hành theo giấy phép Apache-2.0.
Bạn là trưởng Ban Giảm Trùng lặp và Thu gọn Dư thừa. Hiện tại, ban không thể thống nhất liệu chính ban có quá nhiều “thủ tục rườm rà” (sự kém hiệu quả) hay không. Họ yêu cầu bạn thành lập một Ủy ban Thủ tục để biểu quyết vấn đề này.
Ban có \(N\) thành viên. Với mỗi người, bạn biết xác suất \(P_i\) người đó bỏ phiếu “Có”. Nếu không bỏ “Có”, họ chắc chắn bỏ “Không”; không ai bỏ phiếu trắng.
Bạn phải chọn đúng \(K\) thành viên vào ủy ban. Quy định của ban bắt buộc \(K\) là số chẵn để cho phép kết quả hòa, vốn được coi là một phần của bộ máy quan liêu lành mạnh.
Nếu chọn thành viên để tối đa hóa xác suất hòa, xác suất đó là bao nhiêu?
Dòng đầu tiên chứa số bộ test \(T\). Mỗi bộ test gồm hai dòng. Dòng đầu chứa hai số nguyên \(N,K\), là quy mô của ban và của ủy ban. Dòng thứ hai chứa \(N\) số thập phân \(P_i\); mỗi số có đúng hai chữ số sau dấu thập phân và là xác suất thành viên thứ \(i\) bỏ phiếu “Có”.
Với mỗi bộ test, in một dòng Case #x: y, trong đó x là số thứ tự bộ test (bắt đầu từ 1), còn y là số thực: xác suất hòa lớn nhất có thể. y được chấp nhận nếu sai số tuyệt đối hoặc tương đối so với đáp án đúng không vượt quá \(10^{-6}\).
Mỗi Test Set tương ứng với một subtask trên LQDOJ. Bảng dưới đây giữ nguyên điểm chính thức của Google Code Jam và quy đổi tỷ lệ trên tổng điểm của bài.
| Phân nhóm | Điểm Google Code Jam | Tỷ lệ điểm của bài |
|---|---|---|
| Test Set 1 | 5/22 | 22,73% |
| Test Set 2 | 17/22 | 77,27% |
Ví dụ 1
3
2 2
0.50 0.50
4 2
0.00 0.00 1.00 1.00
3 2
0.75 1.00 0.50
Case #1: 0.5
Case #2: 1.0
Case #3: 0.5
Trong bộ test số 1, bạn buộc phải dùng hai thành viên duy nhất. Ủy ban chỉ hòa khi hai người bỏ phiếu khác nhau, điều xảy ra một nửa số lần. Không mất tính tổng quát, hãy cố định phiếu của người thứ nhất; xác suất người thứ hai bỏ ngược lại là 0.5.
Trong bộ test số 2, tốt nhất là chọn một người có xác suất “Có” bằng 0.00 và một người có xác suất bằng 1.00. Điều này bảo đảm hòa.
Trong bộ test số 3, giả sử chọn hai người có xác suất “Có” là 0.50 và 0.75. Hòa xảy ra nếu người thứ nhất bỏ “Có”, người thứ hai bỏ “Không”, xác suất \(0.5\cdot0.25=0.125\); hoặc người thứ nhất bỏ “Không”, người thứ hai bỏ “Có”, xác suất \(0.5\cdot0.75=0.375\). Tổng là \(0.125+0.375=0.5\). Chọn cặp 0.50 và 1.00 cũng cho xác suất hòa 0.5, vì người 1.00 chắc chắn bỏ “Có” và người 0.50 phải bỏ “Không”. Chọn 0.75 và 1.00 chỉ cho xác suất 0.25. Vì vậy 0.5 là tốt nhất.
Google Code Jam 2016, Vòng 2, bài Red Tape Committee.
Nguồn chính thức trên Google Coding Competitions Archive, phát hành theo giấy phép Apache-2.0.
Bạn là Người làm vườn thành Seville, một nhân vật phụ trong một vở opera. Bối cảnh là một sân hình chữ nhật gồm các ô vuông đơn vị, có \(R\) hàng và \(C\) cột. Bạn được yêu cầu dựng một mê cung hàng rào: mỗi ô phải chứa một hàng rào chạy chéo từ góc này sang góc đối diện. Có hai loại hàng rào: từ góc dưới trái đến góc trên phải, ký hiệu /, và từ góc trên trái đến góc dưới phải, ký hiệu \. Khi hai hàng rào chạm nhau, chúng tạo thành một bức tường liên tục.
Bao quanh sân là một vành ngoài gồm các ô đơn vị rộng một ô, bỏ đi bốn ô ở góc. Mỗi ô ngoài là nơi ở của một cận thần. Các cận thần được đánh số theo chiều kim đồng hồ: bắt đầu bằng 1 ở ô ngoài cùng bên trái của hàng trên, và kết thúc bằng \(2(R+C)\) ở ô trên cùng của cột bên trái. Chẳng hạn, với \(R=2\), \(C=2\), khi chưa dựng hàng rào, cách đánh số là:
12
8 3
7 4
65
Trong vở opera kỳ lạ này, tình yêu vừa có qua có lại vừa độc quyền: mỗi cận thần yêu đúng một người khác, và người đó cũng chỉ yêu lại họ. Mỗi người muốn lẻn qua mê cung đến chỗ người yêu mà không gặp bất kỳ cận thần nào khác. Nói cách khác, mỗi cặp yêu nhau phải được nối bằng một lối đi qua mê cung, và lối ấy phải được các bức tường hàng rào ngăn cách với mọi lối khác. Một số phần của mê cung không thuộc lối đi của ai cũng không sao, miễn là mọi cặp người yêu đều được nối.
Cho danh sách các cặp yêu nhau, hãy dựng mê cung hàng rào thỏa mãn yêu cầu, hoặc xác định rằng điều đó là IMPOSSIBLE.
Dòng đầu chứa số bộ test \(T\). Mỗi bộ test gồm một dòng chứa hai số nguyên \(R\) và \(C\), sau đó là một dòng chứa một hoán vị của toàn bộ các số nguyên từ 1 đến \(2(R+C)\). Mỗi số là chỉ số một cận thần; phần tử thứ nhất và thứ hai trong danh sách là một cặp cần nối, phần tử thứ ba và thứ tư là một cặp, và cứ tiếp tục như vậy.
Với mỗi bộ test, trước tiên in một dòng chỉ chứa Case #x:, trong đó x là số thứ tự bộ test, bắt đầu từ 1. Nếu không thể thỏa mãn các điều kiện, in thêm một dòng IMPOSSIBLE. Nếu có thể, in thêm \(R\) dòng, mỗi dòng gồm đúng \(C\) ký tự biểu diễn mê cung; mỗi ký tự phải là / hoặc \, không được để trống ô nào. Nếu có nhiều mê cung hợp lệ, có thể in bất kỳ một mê cung nào.
Mỗi Test Set tương ứng với một subtask trên LQDOJ. Bảng dưới đây giữ nguyên điểm chính thức của Google Code Jam và quy đổi tỷ lệ trên tổng điểm của bài.
| Phân nhóm | Điểm Google Code Jam | Tỷ lệ điểm của bài |
|---|---|---|
| Test Set 1 | 6/29 | 20,69% |
| Test Set 2 | 23/29 | 79,31% |
Ví dụ 1
4
1 1
1 4 3 2
1 3
1 8 2 7 3 4 5 6
2 2
8 1 4 5 2 3 7 6
1 1
1 3 2 4
Case #1:
/
Case #2:
//\
Case #3:
//
\/
Case #4:
IMPOSSIBLE
Trong bộ test 3, các cặp yêu nhau là \((8,1)\), \((4,5)\), \((2,3)\) và \((7,6)\). Hình dưới minh họa đáp án mẫu:
Với bộ test 3, mê cung sau cũng hợp lệ:
/\
\/
Trong bộ test 4, sân chỉ có một ô; đọc theo chiều kim đồng hồ từ phía trên, bốn cận thần là 1, 2, 3, 4. Chỉ có hai cách đặt hàng rào. Dấu / nối 1 với 4 và 2 với 3; dấu \ nối 1 với 2 và 3 với 4. Không cách nào nối được các cặp \((1,3)\) và \((2,4)\), nên kết quả là IMPOSSIBLE và vở opera sẽ đầy những khúc aria buồn!
Google Code Jam 2016, Vòng 2, bài The Gardener of Seville.
Nguồn chính thức trên Google Coding Competitions Archive, phát hành theo giấy phép Apache-2.0.