Tài liệu giải thuật BRESENHAM
Giải thuật BRESENHAMNguyễn Xuân HuyTư tưởng.Trong lập trình, đôi khi chúng taphải làm việc với các số thực. Tính toán với các số thực có hai điều phiền toái.Thứ nhất, do biểu diễn của chúng tốn nhiều đơn vị lưu trữ nên máy tính xử lýcác số thực lâu hơn so với các số nguyên. Thứ hai, phép chia số thực trong máytính có thể cho các kết quả không chính xác. Bạn biết chắc rằng 1/3 + 2/3 =1,trong khi máy tính lại cho bạn kết quả 1/3 + 2/3 = 0.33 + 0.66 = 0.99. Bresenham tìm cách tránh các phép chia số thực thông qua việc tích luỹ dần các đại lượng tỷ lệ và nguyên hóa chúng sau mỗi bước xử lý. Chính vì vậy mà giải thuật này tỏ ra đặc biệt hữu hiệu trongcác bài toán có liên quan đến các phép chia tỷ lệ.Bài toán 1 (Chia kẹo) BàTiên cho hai chị em Quyên và Phong một đống kẹo. Quyên muốn chia cho em theo tỷlệ: chị 5 phần, em 9 phần. Bạn hãy giúp Quyên chia kẹo chính xác đến mức tối đamà không được đếm trước số kẹo.? Ta hãy khoan nói đến việc lậptrình để tập trung vào việc chia kẹo cho chính xác.Lưu ý rằng, ngay cả trong trườnghợp biết trước số kẹo, chúng ta cũng có thể chia không công bằng. Giả dụ, bàTiên cho hai chị em 20 cáI kẹo. Vì chị được 5 phần, em được 9 phần nên tổngcộng có 14 phần cả thảy. Vị chi mỗi phần có 20: 14 = 1 cái kẹo. Do đó Quyên sẽđược nhận 5 cái, Phong được 9 cái. Số kẹo còn dư sẽ là 20 - ( 5+9 ) = 6. Tachia 6 cái kẹo dư này ra sao đây?Chúng ta sẽ giải bài toán trên bằngthuật giải Bresenham.Tỷ lệ giữa chị và em là 5 : 9,chúng ta nhận xét sau:Nếu em nhận được 1 cái kẹo thìchị nhận được 5/ 9 cái.Nếu em nhận được 2 cái kẹo thìchị nhận được 10/ 9 = 1 + 1/ 9 cái.Nếu em nhận được 3 cái kẹo thìchị?nhận được? 1 + 6/ 9 cái. Nếu em nhận được 4 cái kẹo thìchị nhận được? 1 + 11/ 9 cái = 2 + 2/ 9 cái Nếu em nhận được 5 cái kẹo thìchị nhận được? 2 + 7/ 9 cáiNếu em nhận được 6 cái kẹo thìchị nhận được 2 + 12/ 9 = 3 + 3/ 9 cáiNếu em nhận được 7 cái kẹo thìchị nhận được 3 + 8/9 cái Nếu em nhận được 8 cái kẹo thìchị nhận được? 3 + 13/9 cái = 4 + 4/ 9 cáiNếu em nhận được 9 cái kẹo thìchị nhận được 4 + 9/ 9 cái = 5 cáiNếu em nhận được 10 cái kẹo thìchị nhận được 5 + 5/ 9 cái Nếu em nhận được 11 cái kẹo thìchị nhận được 5 + 11/ 9 cái = 6 + 2/ 9 cáiNếu em nhận được 12 cái kẹo thìchị nhận được 6 + 7/ 9 cáiNếu em nhận được 13 cái kẹo thìchị nhận được 6 + 12/ 9 cái = 7 + 3/ 9 cáiTổng số kẹo là 20 do đó ta chiacho em 13 cái và chị nhận 7 cái. Phần thiệt của chị là 3/ 9 cái kẹo là khôngđáng kể.Ta thử tổng quát hóa lời giải trêntrong trường hợp không biết trước tổng số kẹo.Giả sử tỷ lệ kẹo giữa chị và em làn: m, trong đó n <= m.Nếu không biết trước tổng số kẹo,ta cũng theo phương pháp trên, nghĩa là mỗi khi chia cho em một cái kẹo, ta tạmghi nhận chia thêm cho chị n/m cái. Vì đại lượng m không thay đổi trong suốtquá trình chia cho nên ta chỉ cần tích luỹ tử số cho chị. Ta gọi đại lượng tíchlũy tử số này là t. Giá trị ban đầu của t là 0. Mỗi khi em nhận được một chiếckẹo ta cho t tăng thêm n phần trong số m phần của đơn vị. Khi t >= m, tacó phân số t/ m lớn hơn hoặc bằng đơn vị. Lúc này ta chia cho chị một chiếc kẹovà chỉnh lại t:= t - m , vì t/ m = 1 + ( t - m ) / m. Quá trình chia như trênsẽ kết thúc khi số kẹo đã được chia hết.Đến đây chúng ta đã có thể vậndụng giải thuật Bresenham để giải bài toán lý thú sau.Bài toán 2. (Cắt bánh,phỏng theo bài thi học sinh giỏi chuyên tin toàn quốc, khối B)Bà Tiên cho hai chị em Quyên vàPhong một cái bánh hình chữ nhật được ghép bằng nhiều mảnh hình vuông đơn vị.Biết kích thước cái bánh là n x m đơn vị. Chị Quyên cắt bánh theo đường chéo.Hỏi có bao nhiêu ô bánh bị cắt, nghĩa là nhát cắt đi qua hai điểm của ô ( xemhình 1 ).Đếm số ô bị cắt trong cái bánh 5 x 9. Các? dòng (1) và (2) cho biết sự biến thiên của tử số t. Dòng (3) cho biếtsố ô bị cắt được tăng thêm nếu:t ≤ m thì thêm 1; ngược lại khit > m thì thêm 2. Dòng (2) là kết quả chỉnh lại t khi t ≥ m. Có 13 ôbánh được cắt qua được đánh số trong hình.Nói vắn tắt, bài toán 2 yêu cầuđếm số ô vuông đơn vị bị đường chéo của hình chữ nhật cắt qua. Trong thí dụ ởhình 1, kết quả là 13 ô bị cắt. Tuy nhiên với các giá trị n và m lớn , chúngta khó có thể đếm bằng mắt được. Dễ thấy tỷ lệ giữa hai cạnh củahình chữ nhật sẽ là n: m. Ta cần xác định chiều dài của hình, tức là cạnh lớnhơn ( ứng với phần của em trong bài toán chia kẹo ). Giả sử n < m. Chúngta duyệt dần từng điểm i =1 m theo nghĩa chia cho em một chiếc kẹo. Mi lần nhưvậy chị sẽ nhận được thêm n phần trong số m phần của đơn vị . Nếu t ≤ m thìchỉ có đúng 1 ô bi dao cắt qua. Ngược lại, khi t > m sẽ có đúng 2 ô bị daocắt qua. Tóm lại, với mỗi i= i m luôn luôn có một ô bị dao cắt qua. Ta dùngmột biến d để đếm số lượng các ô bị cắt. Giá trị của d được khởi trị là m. Khit > m ta tăng d thêm 1 đơn vị. Ta nhớ chỉnh lại giá trị của t trong cả haitrường hợp: khi t = m và khi t > m.Gọi Cat (n, m) là hàm cho ra số ôbị đường chéo của hình chữ nhật kích thước n x m cắt. Sơ đồ tính toán chohàm Cat khi đó sẽ như sau:Sơ đồ cho hàm Cat- Hoán vị, nếu cần để cho n <> - Khởi trị:+ Con đếm d:= m, vì chắcchắn có ít nhất là m ô bị cắt; + Giá? trị của tử số t:= 0;- Tính với mỗi i = 1 m+ Tăng thêm t một lượng m + Nếu t > m tăng d thêm 1đơn vị + Nếu t >= m chỉnh lạit:= t - mHàm CatFunction Cat (n, m: word): word;Var t, i, d : word;BeginIf n > m thenBegint:= m;m:= n; n:= t;End;t:= 0; d:=m;for i:= 1 to m dobegint:=t + n;if t > m then inc (d);if t>= m then t:= t - m;end;Cat:=d;End;Chương trình Pascal: CATBANH.PASUses crt;Function Cat (n, m: word): word;Var t, i, d: word;BeginIf n > m thenBeginT:= m;M:= n;N:= t;End;T:=0; d:=m; For i:=1 to m doBeginT:= t + n;If t > m then inc (d)If t >= m then t:= t - m;End;Cat:= d;End;Procedure Test;Var n, m : word;BeginClrscr;RepeatWriteln;Write( Nap n, m:);Readln(n, m);If (n=0) or (m=0) then exit;Writeln (Cat (n, m));Until false;End;BEGINTest;END. Độ phức tạp tính toánHàm Cat duyệt m lần. Vậy độ phứctạp tính toán sẽ là max (n, m), trong đó m và n là độ dài hai cạnh hình chữnhật.Test chương trìnhChương trình nhận vào cùng một lúchai số tự nhiên n và m là chiều dài hai cạnh của hình chữ nhật. Bạn nhớ nạp haigiá trị này từ bàn phím, giữa chúng đặt dấu cách. Để Test được tốt ta lưu ývài tính chất sau đây của hàm CatCat (n, m) = Cat (m, n)Cat (n, n) = nCat (1, m) = mCat (d*n, d*m) = d* Cat (n, m) Phần chứng minh dành cho bạn đọc.ứng dụngGiải thuật Bresenham được ứng dụngrộng rãi trong đồ hoạ máy tính. Bản chất của hàm Cat nói trên chính là thuậttoán vẽ đoạn thẳng qua hai điểm cho trước. Hai điểm này chính là hai đỉnh đốidiện của một hình chữ nhật. Mỗi ô bị cắt sẽ ứng với một điểm nằm trên đoạnthẳng cần vẽ.Bài tập 1.Chứng minh tính chất 5 sau đây củahàm Cat sau đó vận dụng để cải tiến đoạn mã của hàm.1. Cat(n, m)= d*cat(n div d, m div d), trong đó d là ước chung lớn nhất của m và n.Xin cung cấp cho các bạn hàm tìm ước chung lớn nhấtcủa hai số tự nhiên.Function Ucln (a,b: word): word;var r: wordBeginwhile b <> 0 dobegin r: = amod b;a:= b;b:= r;end;Ucln:=a;End; Bài tập 2. Người ta chồngcác khối lập phương đơn vị để tạo thành một hình hộp chữ nhật chiều cao h, đáytrên ABCD có kích thước AB=a, BC=b. Trên các cạnh của đáy trên lần lượt lấy?các điểm M trên? AB, N trên BC, P trên CD và Q trên DA. Biết AM=m, BN=n; CP=pvà DQ=q. Mọi giá trị đều là những số nguyên dương. Người ta dùng dao sắc cắt 4nhát từ trên xuống dưới theo chiều thẳng đứng. Nhát cắt đi qua các đoạn MN, NP,PQ và QM. Có bao nhiêu khối lập phương đơn vị bị dao cắt hẳn vào phía trong?Nguyễn Xuân Huy . 5+9 ) = 6. Tachia 6 cái kẹo dư này ra sao đây?Chúng ta sẽ giải bài toán trên bằngthuật giải Bresenham. Tỷ lệ giữa chị và em là 5 : 9,chúng ta nhận xét sau:Nếu. khi số kẹo đã được chia hết.Đến đây chúng ta đã có thể vậndụng giải thuật Bresenham để giải bài toán lý thú sau.Bài toán 2. (Cắt bánh,phỏng theo bài thi