Bạn có muốn phản ứng với tin nhắn này? Vui lòng đăng ký diễn đàn trong một vài cú nhấp chuột hoặc đăng nhập để tiếp tục.


 
Trang ChínhLatest imagesĐăng kýĐăng Nhập
Latest topics
» Assistance With Transplant Drugs
by Khách viếng thăm Thu Aug 04, 2011 1:11 am

» Drug Fair Cranford Nj
by Khách viếng thăm Sun Jul 31, 2011 8:30 pm

» Drug Formulary For Medicare
by Khách viếng thăm Thu Jul 28, 2011 3:52 pm

» lop 86 truong an phuoc
by cudinh@ Mon Nov 15, 2010 9:59 am

» Hu hu hu Bó tay
by cudinh@ Mon Nov 15, 2010 9:55 am

» nguyễn ngọc thông
by cudinh@ Mon Nov 15, 2010 9:31 am

» Đọc và suy nghĩ
by SiVi_Ph Fri Jan 29, 2010 2:44 pm

» yêu dể chết trong lòng....1 tá(>.<)
by IT'S UP TO YOU Thu Jan 21, 2010 10:14 pm

» Giáo án lớp mình nè
by Admin Mon Jan 18, 2010 7:31 pm

» Giáo an lớp 7 cả năm
by Admin Wed Oct 14, 2009 4:08 pm

» Giáo an lớp 7 toàn tập
by Admin Wed Oct 14, 2009 4:06 pm

» Giáo an lớp 6 toàn tập
by Admin Wed Oct 14, 2009 4:03 pm



bài toán mã đi tuần đây bà conXem chủ đề cũ hơn Xem chủ đề mới hơn Go down

Copy đường link dưới đây gửi đến nick yahoo bạn bè!

Wed Sep 03, 2008 10:46 am
suphu
suphu
Năm Ba
Năm Ba
Nam Tổng số bài gửi : 8
Cảnh cáo : Không có cảnh cáo gì
Tâm Trạng của bạn : Cô đơnVui vẻBuồn bảMệt mỏi
Registration date : 20/08/2008

bài toán mã đi tuần đây bà con Vide
Bài gửiTiêu đề: bài toán mã đi tuần đây bà con

Chúng tôi nghĩ là giải thuật backtracking giải bài toán “Mã đi tuần” đã được trình bày trong tài liệu mà bạn đọc. Và nếu nắm vững giải thuật thì về nguyên tắc bạn sẽ dịch được giải thuật ra chương trình máy tính dùng ngôn ngữ mà bạn ưa thích. Sau đây chúng tôi liệt kê chương trình Pascal giải bài toán này theo yêu cầu của bạn, lưu ý là giải thuật dựa trên bước lặp cơ bản như sau: nếu con mã đang ở vị trí ô cờ (i,j) thì nó có thể đi tiếp 1 trong 8 khả năng khác nhau xung quanh ô (i,j) hiện tại, chúng ta sẽ lần lượt thử cho con mã đi từng khả năng, nếu được thì tốt, nếu cả 8 khả năng đều không đi được ta sẽ lùi con mã về vị trí ô cờ ngay trước đó rồi tiếp tục thử các khả năng chưa thử. Chương trình dùng 2 biến dữ liệu chính là:

• Biến Banco là 1 dãy 8*8 phần tử, mỗi phần tử miêu tả thứ tự nước đi của con mã (từ 0 tới 63), nếu vị trí nào con mã chưa đi qua sẽ có giá trị đầu là -1 để phân biệt.

• Biến Nuocdi là 1 danh sách 64 phần tử lưu giữ trình tự các vị trí ô cờ mà con mã đi qua từ vị trí xuất phát nào đó do user qui định, mỗi vị trí đi qua ta nhớ lại tọa độ (i,j) và chỉ số hướng đi đã thử. Tất cả chỉ số của các dãy đều bắt đầu từ 0.
bắt đầu chương trình đây:

Program MadiTuan;

{Chỉ số hàng cột lớn nhất của bàn cờ : thường là 7}

Const Max = 7;

{Kiểu dữ liệu chứa thông tin của 1 bước đi}

Type ItemRec = Record

x, y : Integer;

huong : Integer;

End;

{ Các biến dữ liệu chính}

Var Banco: Array [0..7,0..7] of Integer;

Nuocdi: Array [0..63] of ItemRec;

SoNuocdi : Integer;

cach : Integer;

{Thủ tục khởi động các giá trị đầu của chương trình}

Procedure Khoidong;

Var i,j : Integer;

Begin

cach := 0;

for i:=0 to Max do

for j:= 0 to Max do

Banco[i,j] := -1;

write(‘Nhập tọa độ hàng chứa con mã : ‘);

readln(Nuocdi[0].y);

write(‘Nhập tọa độ cột chứa con mã : ‘);

readln(Nuocdi[0].x);

Nuocdi[0].huong := 0;

{Thiết lập nước đi đầu tiên của con mã}

SoNuocdi :=0;

Banco[Nuocdi[SoNuocdi].x,Nuocdi[SoNuocdi].y] := 0;

End;



{In kết quả con mã đi trên bàn cờ}

Procedure InKetqua;

Var h,c : Integer;

Begin

cach := cach + 1;

writeln(‘Cách đi thứ : ‘,cach);

for h:= 0 to Max do begin

{ Hiển thị hàng lưới ngang bàn cờ }

for c:= 0 to Max do write(‘+——’);

writeln(‘+’);

{ Hiển thị nội dung hàng thứ h bàn cờ }

for c:= 0 to Max do

write(‘| ‘,Banco[h,c]:2,’ ‘);

writeln(‘|’);

end;

{Hiển thị hàng lưới ngang bàn cờ cuối cùng}

for c:= 0 to Max do write(‘+——’);

writeln(‘+’);

{readln;}

End;



{Thủ tục tìm nước đi kế tiếp}

Function TimNuocKe : Boolean;

Var x, y : Integer;

RetVal : Boolean;

Begin

RetVal := False;

Repeat {lặp tìm nước đi kế tiếp đến khi tìm được hoặc hết cách đi}

while (RetVal=False) and (Nuocdi[SoNuocdi].huong < Cool do begin

Case Nuocdi[SoNuocdi].huong of {thử hướng đi hiện tại}

0 : begin

x := Nuocdi[SoNuocdi].x + 2;

y := Nuocdi[SoNuocdi].y - 1;

end;

1 : begin

x := Nuocdi[SoNuocdi].x + 1;

y := Nuocdi[SoNuocdi].y - 2;

end;

2 : begin

x := Nuocdi[SoNuocdi].x - 1;

y := Nuocdi[SoNuocdi].y - 2;

end;

3 : begin

x := Nuocdi[SoNuocdi].x - 2;

y := Nuocdi[SoNuocdi].y - 1;

end;

4 : begin;

x := Nuocdi[SoNuocdi].x - 2;

y := Nuocdi[SoNuocdi].y + 1;

end;

5 : begin

x := Nuocdi[SoNuocdi].x - 1;

y := Nuocdi[SoNuocdi].y + 2;

end;

6 : begin

x := Nuocdi[SoNuocdi].x + 1;

y := Nuocdi[SoNuocdi].y + 2;

end;

7 : begin

x := Nuocdi[SoNuocdi].x + 2;

y := Nuocdi[SoNuocdi].y + 1;

end

End;

if (0<=x) and (x<=Max) and (0<=y) and (y<=Max) and (Banco[x,y]=-1) then begin

{nếu được thì ghi nhận}

SoNuocdi := SoNuocdi + 1;

Banco[x,y] := SoNuocdi;

Nuocdi[SoNuocdi].x := x;

Nuocdi[SoNuocdi].y := y;

Nuocdi[SoNuocdi].huong := 0;

RetVal:=True;

end else

{nếu không được thì thủ hướng kế tiếp}

Nuocdi[SoNuocdi].huong := Nuocdi[SoNuocdi].huong + 1;

end;

if (RetVal=False) and (SoNuocdi <> 0) then begin

{nếu không tìm được nước đi kế thì lùi con mã lại 1 bước}

Banco[Nuocdi[SoNuocdi].x,Nuocdi[SoNuocdi].y] := -1;

SoNuocdi := SoNuocdi - 1;

Nuocdi[SoNuocdi].huong := Nuocdi[SoNuocdi].huong + 1;

end

until RetVal or (SoNuocdi = 0);

TimNuocKe := RetVal;

End;



{Chương trình chính}

Begin

Khoidong;

while TimNuocKe do begin

if SoNuocdi = (Max+1)*(Max+1)-1 then begin

{nếu tìm được 1 nghiệm}

InKetqua;

Banco[Nuocdi[SoNuocdi].x,Nuocdi[SoNuocdi].y] := -1;

SoNuocdi := SoNuocdi -1;

Nuocdi[SoNuocdi].huong := Nuocdi[SoNuocdi].huong + 1;

end

end

End.

Lưu ý giải thuật backtracking thuộc loại giải thuật vét cạn nên thường có thời gian tính toán rất lớn, cụ thể với bài toán trên nếu kích thước bàn cờ là 8*8 thì giải thuật sẽ phải xét 864 = 2192 hướng đi, các máy PC hiện tại (ngay cả Pentium IV 3,1GHz) cũng phải tốn hàng tỉ tỉ năm mới chạy xong giải thuật. Do đó để tìm được kết quả thực sự, bạn nên chọn kích thước bàn cờ 4,5,6 là vừa (khai báo lại hằng Max = 3,4,5).
Chúng tôi nghĩ là giải thuật backtracking giải bài toán “Mã đi tuần” đã được trình bày trong tài liệu mà bạn đọc. Và nếu nắm vững giải thuật thì về nguyên tắc bạn sẽ dịch được giải thuật ra chương trình máy tính dùng ngôn ngữ mà bạn ưa thích. Sau đây chúng tôi liệt kê chương trình Pascal giải bài toán này theo yêu cầu của bạn, lưu ý là giải thuật dựa trên bước lặp cơ bản như sau: nếu con mã đang ở vị trí ô cờ (i,j) thì nó có thể đi tiếp 1 trong 8 khả năng khác nhau xung quanh ô (i,j) hiện tại, chúng ta sẽ lần lượt thử cho con mã đi từng khả năng, nếu được thì tốt, nếu cả 8 khả năng đều không đi được ta sẽ lùi con mã về vị trí ô cờ ngay trước đó rồi tiếp tục thử các khả năng chưa thử. Chương trình dùng 2 biến dữ liệu chính là:

• Biến Banco là 1 dãy 8*8 phần tử, mỗi phần tử miêu tả thứ tự nước đi của con mã (từ 0 tới 63), nếu vị trí nào con mã chưa đi qua sẽ có giá trị đầu là -1 để phân biệt.

• Biến Nuocdi là 1 danh sách 64 phần tử lưu giữ trình tự các vị trí ô cờ mà con mã đi qua từ vị trí xuất phát nào đó do user qui định, mỗi vị trí đi qua ta nhớ lại tọa độ (i,j) và chỉ số hướng đi đã thử. Tất cả chỉ số của các dãy đều bắt đầu từ 0.
bắt đầu chương trình đây:

Program MadiTuan;

{Chỉ số hàng cột lớn nhất của bàn cờ : thường là 7}

Const Max = 7;

{Kiểu dữ liệu chứa thông tin của 1 bước đi}

Type ItemRec = Record

x, y : Integer;

huong : Integer;

End;

{ Các biến dữ liệu chính}

Var Banco: Array [0..7,0..7] of Integer;

Nuocdi: Array [0..63] of ItemRec;

SoNuocdi : Integer;

cach : Integer;

{Thủ tục khởi động các giá trị đầu của chương trình}

Procedure Khoidong;

Var i,j : Integer;

Begin

cach := 0;

for i:=0 to Max do

for j:= 0 to Max do

Banco[i,j] := -1;

write(‘Nhập tọa độ hàng chứa con mã : ‘);

readln(Nuocdi[0].y);

write(‘Nhập tọa độ cột chứa con mã : ‘);

readln(Nuocdi[0].x);

Nuocdi[0].huong := 0;

{Thiết lập nước đi đầu tiên của con mã}

SoNuocdi :=0;

Banco[Nuocdi[SoNuocdi].x,Nuocdi[SoNuocdi].y] := 0;

End;



{In kết quả con mã đi trên bàn cờ}

Procedure InKetqua;

Var h,c : Integer;

Begin

cach := cach + 1;

writeln(‘Cách đi thứ : ‘,cach);

for h:= 0 to Max do begin

{ Hiển thị hàng lưới ngang bàn cờ }

for c:= 0 to Max do write(‘+——’);

writeln(‘+’);

{ Hiển thị nội dung hàng thứ h bàn cờ }

for c:= 0 to Max do

write(‘| ‘,Banco[h,c]:2,’ ‘);

writeln(‘|’);

end;

{Hiển thị hàng lưới ngang bàn cờ cuối cùng}

for c:= 0 to Max do write(‘+——’);

writeln(‘+’);

{readln;}

End;



{Thủ tục tìm nước đi kế tiếp}

Function TimNuocKe : Boolean;

Var x, y : Integer;

RetVal : Boolean;

Begin

RetVal := False;

Repeat {lặp tìm nước đi kế tiếp đến khi tìm được hoặc hết cách đi}

while (RetVal=False) and (Nuocdi[SoNuocdi].huong < Cool do begin

Case Nuocdi[SoNuocdi].huong of {thử hướng đi hiện tại}

0 : begin

x := Nuocdi[SoNuocdi].x + 2;

y := Nuocdi[SoNuocdi].y - 1;

end;

1 : begin

x := Nuocdi[SoNuocdi].x + 1;

y := Nuocdi[SoNuocdi].y - 2;

end;

2 : begin

x := Nuocdi[SoNuocdi].x - 1;

y := Nuocdi[SoNuocdi].y - 2;

end;

3 : begin

x := Nuocdi[SoNuocdi].x - 2;

y := Nuocdi[SoNuocdi].y - 1;

end;

4 : begin;

x := Nuocdi[SoNuocdi].x - 2;

y := Nuocdi[SoNuocdi].y + 1;

end;

5 : begin

x := Nuocdi[SoNuocdi].x - 1;

y := Nuocdi[SoNuocdi].y + 2;

end;

6 : begin

x := Nuocdi[SoNuocdi].x + 1;

y := Nuocdi[SoNuocdi].y + 2;

end;

7 : begin

x := Nuocdi[SoNuocdi].x + 2;

y := Nuocdi[SoNuocdi].y + 1;

end

End;

if (0<=x) and (x<=Max) and (0<=y) and (y<=Max) and (Banco[x,y]=-1) then begin

{nếu được thì ghi nhận}

SoNuocdi := SoNuocdi + 1;

Banco[x,y] := SoNuocdi;

Nuocdi[SoNuocdi].x := x;

Nuocdi[SoNuocdi].y := y;

Nuocdi[SoNuocdi].huong := 0;

RetVal:=True;

end else

{nếu không được thì thủ hướng kế tiếp}

Nuocdi[SoNuocdi].huong := Nuocdi[SoNuocdi].huong + 1;

end;

if (RetVal=False) and (SoNuocdi <> 0) then begin

{nếu không tìm được nước đi kế thì lùi con mã lại 1 bước}

Banco[Nuocdi[SoNuocdi].x,Nuocdi[SoNuocdi].y] := -1;

SoNuocdi := SoNuocdi - 1;

Nuocdi[SoNuocdi].huong := Nuocdi[SoNuocdi].huong + 1;

end

until RetVal or (SoNuocdi = 0);

TimNuocKe := RetVal;

End;



{Chương trình chính}

Begin

Khoidong;

while TimNuocKe do begin

if SoNuocdi = (Max+1)*(Max+1)-1 then begin

{nếu tìm được 1 nghiệm}

InKetqua;

Banco[Nuocdi[SoNuocdi].x,Nuocdi[SoNuocdi].y] := -1;

SoNuocdi := SoNuocdi -1;

Nuocdi[SoNuocdi].huong := Nuocdi[SoNuocdi].huong + 1;

end

end

End.

Lưu ý giải thuật backtracking thuộc loại giải thuật vét cạn nên thường có thời gian tính toán rất lớn, cụ thể với bài toán trên nếu kích thước bàn cờ là 8*8 thì giải thuật sẽ phải xét 864 = 2192 hướng đi, các máy PC hiện tại (ngay cả Pentium IV 3,1GHz) cũng phải tốn hàng tỉ tỉ năm mới chạy xong giải thuật. Do đó để tìm được kết quả thực sự, bạn nên chọn kích thước bàn cờ 4,5,6 là vừa (khai báo lại hằng Max = 3,4,5).

Vote cho bài viết:
Xem chủ đề cũ hơn Xem chủ đề mới hơn Về Đầu Trang

bài toán mã đi tuần đây bà con

Xem chủ đề cũ hơn Xem chủ đề mới hơn Về Đầu Trang
Trang 1 trong tổng số 1 trang

Permissions in this forum:Bạn không có quyền trả lời bài viết
 :: Luôn luôn lắng nghe.., lâu lâu mới hiểu :: Chia sẽ cùng nhau-
Múi giờ GMT +7. Hiện tại là 04:31 PM
Style SPTK32 - Designed by Skinner