Bài 2: Những con đường quanh nông trang

Một phần của tài liệu MỘT số vấn đề về KIỂU dữ LIỆU TRỪU TƯỢNG (Trang 55)

Chương IV: BÀI TẬP ỨNG DỤNG

Bài 2: Những con đường quanh nông trang

Các con bò của nông dân John có sở thích là hay đi khám phá những vùng xung quanh nông trang. Ban đầu, tất cả N (1 <= N <= 1,000,000,000) con bò tập trung thành 1 nhóm và cùng bắt đầu chuyến đi trên 1 con đường. Cho tới khi gặp một ngã ba đường thì chúng đôi khi chọn cách chia làm 2 nhóm nhỏ hơn ( mỗi nhóm ít nhất 1 bò ) và mỗi nhóm lại tiếp tục hành trình trên con đường của nhóm chúng. Khi một trong những nhóm này gặp 1 ngã ba khác thì nhóm này lại có thể tách ra tiếp, và cứ như vậỵ

Các con bò đã hình thành nên 1 quy tắc về việc chia nhóm như sau: nếu chúng có thể chia thành 2 nhóm mà chênh lệch số bò của 2 nhóm là đúng bằng K (1 <= K <= 1000) thì tại ngã ba đó chúng sẽ chia làm 2; nếu không thì chúng sẽ dừng cuộc hành trình và đứng ở đó nhấm nháp cỏ non.

Giả sử rằng luôn có những ngã ba mới trên các con đường, hãy tính xem cuối cùng có bao nhiêu nhóm bò tất cả.

Kết quả: Một số nguyên cho biết số lượng nhóm bò sau cùng. Ví dụ: VRATF.INP VRATF.OUT 6 2 3 Giải thích: Cuối cùng có 3 nhóm bò (1 nhóm có 2 bò, 1 nhóm có 1 và 1 nhóm có 3 ). 6 / \ 2 4 / \ 1 3 Hướng dẫn:

Bài trên các bạn có thể dùng đệ quy để giải một cách hữu hiệu, nhưng chúng ta có thể sử dụng Stack và Queue để giải quyết.

Sau đây là ý tưởng sử dụng hàng đợi để giải quyết bài này:

Gọi kq là kết quả cần tìm. Ban đầu khởi tạo Queue có duy nhất một phần tử đó là số bò ban đầu và kq:=0;

Thực hiên các công việc sau chừng nào Queue rỗng thì thôi: + Lấy một phần tử ra khỏi hàng đợi gán vào n.

+ Nếu ((n-k) mod 2=1) or (n<=k) thì tăng kq lên 1: kq:=kq+1;{ Khi n<=k thì có nghĩa không thể chia được nữa, (n-k) mod 2 =1 có nghĩa là không thể chia thành hai nhóm mà chênh lệch số lượng đúng bằng k, khi đó chúng sẽ dừng lại và gặm cỏ, khi đó ta có thêm một nhóm mới nên kq:=kq+1}

+ Trái lại thì ta có thể chia thành hai nhóm mà chênh lệch số lượng đúng bằng k, như vậy nhóm một sẽ có a=(n-k) div 2 con bò, nhóm 2 sẽ có b=n-a con bò.Ta đẩy a và b vào hàng đợị

Note: Tuy n<= nhưng ta chỉ cần khai báo số phần tử tối đa của Queue là 10000 là quá đủ rồị

Cài đặt chương trình:

Đây là một bài toán khá đơn giản vì vậy tôi chỉ viết thủ tục chính các thủ tục còn lại các bạn tự viết. Procedure solution; Var a,b :longint; Begin PushQ(n); kq:=0;

{kq va n la bien khai bao o chuong trinh chinh} While not Empty do

Begin

PopQ(n);

if (n mod 2=1) or (n<=k) then inc(kq) else

a:=(n-k) div 2; b:=n-a; PushQ(a); PushQ(b); End; End; End;

Tôi xin giới thiệu các bạn thủ tục đệ quy như sau:

Hàm Find(n:longint):longint trả về số nhóm bò cuối cùng khi có n con bò: Function find(n:longint):longint;

Begin

if (n mod 2=1) or (n<=k) then exit(1) else

find:=find((n-k) div 2))+find((n-k) div 2+k); End;

Ta thấy thủ tục đệ quy trên khá ngắn gọn tuy với n<=1000000000 nó chạy tương đối nhanh nhưng khi mở rộng ra nó tỏ ra chậm hơn nhiều so với cách sử dụng hàng đợị Tuy nhiên khi đi thi tôi khuyên nên sử dụng một cách hợp lý các thuật toán, không nhưng tốc độ nhanh mà còn đòi hỏi cài đặt càng đơn giản càng tốt. Nếu là tôi tôi sẽ chọn cách đệ quỵ

Bài 3: Huyền thoại Lục Vân Tiên

Một phần của tài liệu MỘT số vấn đề về KIỂU dữ LIỆU TRỪU TƯỢNG (Trang 55)

Tải bản đầy đủ (DOC)

(76 trang)
w