1. Trang chủ
  2. » Công Nghệ Thông Tin

Bài toán chơi cờ trong Pascal

8 1,7K 30
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 8
Dung lượng 96,5 KB

Nội dung

Bài toán chơi cờ trong Pascal

Ngày xuân lập trình chơi cờ bảngNguyễn Xuân HuyBài toán Tab game (Cờ bảng)Cờ bảng gồm một bảng N x M ô vuông đơn vị và một quân cờ kí hiệu là @. Các dòng của bảng được mã số 1 N từ dưới lên, các cột được mã số 1 M từ trái qua phải. Lúc đầu quân cờ @ được đặt tại một ô (x,y) gọi là ô xuất phát. Hai đấu thủ là A và B lần lượt di chuyển quân cờ, A luôn đi trước trong mọi ván cờ. Luật chơi như sau:Đến lượt ai, người đó nhiệm vụ di chuyển quân cờ đang đặt tại cột i sang cột k ≠ i theo cách sau: - Thoạt tiên chuyển dọc quân cờ lên k dòng, nếu quân cờ chưa ra khỏi giới hạn bàn cờ thì tiếp tục chuyển quân cờ (rẽ phải hoặc trái) sang cột k.- Đấu thủ nào, đến lượt mình, không tìm được cách nào di chuyển quân cờ thì sẽ thua. Ván cờ kết thúc.Thí dụ, với bàn cờ 10 x 4, quân cờ @ đặt tại vị trí (5,3) thì A thể di chuyển quân cờ đến các ô (6,1), (7,2) hoặc (9,4). Yêu cầu: Hãy cho biết A thể thắng hay không? Trong trường hợp A thắng, hãy cho biết A thể thắng sau tối đa bao nhiêu nước đi với giả thiết là hai đấu thủ A và B đều chơi rất giỏi và mỗi lượt A hoặc B đi được gọi là một nước đi.Trong thí dụ trên, khi quân cờ được đặt tại vị trí xuất phát (5,3) thì A thua.Ngược lại, nếu chọn vị trí xuất phát là (4,3) thì A thể thắng sau 2 nước đi (xem hình 1). Dữ liệu vào: Tệp văn bản tab.inp:Dòng đầu tiên là số lượng test s, 1 ≤ s ≤ 10.Tiếp đến là s dòng, mỗi dòng là một test gồm 4 số tự nhiên cách nhau ít nhất một dấu cách, N M x y, trong đó• N - số lượng dòng của bảng, 1 ≤ s ≤ 200,• M - số lượng cột của bảng, 1 ≤ s ≤ 50,• x - tọa độ dòng xuất phát của quân cờ,• y - tọa độ cột xuất phát của quân cờ.Dữ liệu ra: Tệp văn bản tab.out:Gồm s dòng, dòng thứ i chứa kết quả của test thứ i, cụ thể là chứa duy nhất một số tự nhiên d với nghĩa sau,• d = 0: nếu A thua,• d > 0: nếu A thắng sau d nước đi.Thí dụ: Bài giảiĐây là một bài toán khó thuộc lớp các bài toán trò chơi, tuy nhiên lời giải là dễ hiểu và đặc biệt là thuật giải bài toán này thể vận dụng cho một số bài toán khác. a. Trước hết chúng ta hãy giảm nhẹ yêu cầu của bài toán, cụ thể là chúng ta chỉ yêu cầu xác định đấu thủ đi nước đầu tiên là A sẽ thắng (ghi đáp số là 1) hay thua (ghi đáp số là 0).Phương án này thể giải dễ dàng bằng quy hoạch động như sau:Lần lượt điền các giá trị 0 và 1 vào các ô trong từng dòng của bảng, theo trật tự từ dòng cao nhất, dòng thứ N đến dòng thấp nhất, dòng 1. Trên mỗi dòng ta lần lượt điền từ trái qua phải, tức là từ cột 1 đến cột M. Gọi mảng chứa dữ liệu của bàn cờ là a, ta quy định a[i,j] = 0 nếu xuất phát từ ô (i,j) đến lượt ai đi thì sẽ thua, ngược lại, a[i,j] = 1 thì người nào đến lượt đi sẽ thắng. Để tiện trình bày, ta sẽ gọi ô chứa trị 0 là ô 0 (ô không) hay ô (dẫn đến) thua , ô chứa trị 1 là ô 1 hay ô (dẫn đến) thắng. Ta thấy dòng N sẽ chứa toàn 0, vì đó là các thế “cùng”, tức là các thế thua. Từ dòng N-1 trở xuống ta tính trị cho các ô như sau. Từ ô (i,j), nếu một cách di chuyển quân cờ đến ô 0 là ô đẩy đối phương vào thế thua, thì người cầm quân sẽ thắng, ngược lại, nếu không cách nào, hay với mọi cách đi người cầm quân chỉ thể di chuyển quân cờ đến các ô 1 thì anh ta sẽ thua, vì sau anh ta, đến lượt đối phương sẽ được “hưởng” thế thắng tại các ô nhận trị 1.Khung của lời giải thể hiện trong thủ tục run sẽ như sau: 1. Mở tệp input tab.inp để đọc dữ liệu vào.2. Mở tệp output tab.out để chuẩn bị ghi kết quả.3. Đọc số lượng test vào biến sotest.4. Với mỗi test 4.1. Đọc các giá trị N, M, x và y từ tệp input tab.inp, trong đó N và M là kích thước bàn cở, (x,y) là tọa độ xuất phát của quân cờ.4.2. Gọi thủ tục tab để điền trị cho mảng a là mảng biểu thị bàn cờ.4.3. Ghi a[x,y] là kết quả chơi ván cờ của đấu thủ A ứng với test đã cho với giả thiết là A đi trước. 5. Đóng các tệp input và output.procedure run;var i: integer;beginassign(f,fn); reset(f);assign(g,gn); rewrite(g);readln(f,sotest);for i:=1 to sotest dobeginreadln(f,n,m,x,y); tab;writeln(g,a[x,y]); end;close(f); close(g); end;Thủ tục tab được thể hiện như sau,1. Khởi trị toàn 0 cho mảng a.2. Với mỗi dòng từ N-1 đến 1 Với mỗi cột từ 1 đến M Điền trị cho ô a[i,j] theo thủ tục value(i,j).3. Nhận a[x,y] làm đáp số. Dừng thủ tục. procedure tab;var i,j: integer;beginfillchar(a,sizeof(a),0);for i:=n-1 downto 1 dofor j:=1 to m do value(i,j);end;Thủ tục điền trị cho ô (i,j), value(i,j) hoạt động như sau:1. Đầu tiên ta duyệt các cột trước j, cụ thể là các cột k:=1 (j-1) và xét xem thể di chuyển quân cờ @ đến ô (i+k,k) để đảm bảo chắc thắng hay không. Quân cờ @ chuyển được đến ô (i+k,k) khi và chỉ khi (i) thể chuyển @ đến dòng i+k vẫn nằm trong giới hạn của bàn cờ, tức là i+k ≤ N,(ii) Nếu chuyển @ đến ô (i+k,k) thì người cầm quân chắc thắng, hay là người đi tiếp sẽ thua, tức là a[i+k,k] = 0. 2.Tiếp đến ta duyệt các cột sau j, cụ thể là các cột k từ j+1 đến M theo cùng cách thức như trên.Nếu tìm được một ô thỏa hai điều kiện thắng (i) và (ii) thì ta gán trị cho a[i,j] = 1 với ý nghĩa là người cầm quân đi từ ô (i,j) đó sẽ chắc thắng, sau đó dừng tủ tục value.Ngược lại, nếu đã duyệt mọi cột k:= 1 j-1, j+1 M mà không tìm được ô nào thỏa hai điều kiện thắng nói trên thì đành chọn ô tùy ý, miễn là đi được theo đúng luật chơi. Trong trường hợp này ta phải gán trị a[i,j] = 0 với ý nghĩa là người cầm quân sẽ thua, sau đó dừng thủ tục value.{ xac dinh gia tri cho o a[i,j];a[i,j] = 0: Ai di tu o do se thuaa[i,j] = 1: Ai di tu o do se thang }procedrue value(i,j: integer);var k: integer;begin a[i,j]:=1; { Gán trước trị thắng }{ Duyet cac o truoc cot j } for k:=1 to j-1 doif i+k <= n { trong ban co } thenif a[i+k,k] = 0 then exit;{ Duyet cac o sau cot j } for k:=j+1 to m doif i+k <= n { trong ban co } thenif a[i+k,k] = 0 then exit;a[i,j]:=0;end;Thuật toán trên tên gọi là thuật toán min-max. Chương trình hoàn chỉnh cho phương án đầy đủ cuối cùng sẽ như sau. (* Phuong an day du *) program tab;uses crt;constfn = 'tab.inp'; gn = 'tab.out';bl = #32; nl = #13#10;nn = 201; mm = 51; type mb1 = array[0 mm] of shortint;mb2 = array[0 nn] of mb1;var f,g: text; { files input, output }n,m: integer; { kich thuoc bang }x,y: integer; { toa do xuat phat cua quan co }sotest: integer; a: mb2;{ mang 2 chieu chua du lieu mo phong ban co }{--------------------------------------------------xac dinh tri cho o (i,j). Chon o (i+k,k)de chuyen quan tu (i,j) den do, sao cho chac thang ---------------------------------------------------}procedure value(i,j: integer);var k,maxthua,minthang: integer;beginmaxthua:=0; minthang:=-127;for k:=1 to j-1 doif i+k <= n thenif a[i+k,k] <= 0 thenbegin{ duyet o am: Ai di chuyen quan vao day se thangnen can chon o de thang nhanh nhat }if minthang < a[i+k,k] then minthang:=a[i+k,k]endelsebegin{ duyet o duong: Ai di vao day se thuanen can chon o de thua cham nhat }if maxthua < a[i+k,k] then maxthua:=a[i+k,k];end;for k:=j+1 to m doif i+k <= n thenif a[i+k,k] <= 0 thenbegin{ duyet o am: Ai di chuyen quan vao day se thangnen can chon o de thang nhanh nhat }if minthang < a[i+k,k] then minthang:=a[i+k,k]endelsebegin{ duyet o duong: Ai di vao day se thuanen can chon o de thua cham nhat }if maxthua < a[i+k,k] then maxthua:=a[i+k,k];end;{ uu tien cho kha nang thang } if minthang <> -127 then a[i,j]:= -(minthang-1)else a[i,j]:= -(maxthua+1);end;procedure tab;var i,j: integer;beginfillchar(a,sizeof(a),0);{ xu ly rieng cac phan tu 2 M cua dong 2 }for j:=2 to m do value(n-1,j);for i:=n-2 downto 1 dofor j:=1 to m do value(i,j);end;procedure run;var i: integer;beginassign(g,gn); rewrite(g);assign(f,fn); reset(f);readln(f,sotest);for i:=1 to sotest dobeginreadln(f,n,m,x,y);tab;{ Ghi ket qua }if a[x,y] < 0 then writeln(g,0) else writeln(g,a[x,y]);end;close(f); close(g);end;BEGINrun;readln;END.Một bài toán ứng dụng: Jump Game (Cờ nhảy).Mời các bạn vui Xuân bằng bàn cờ nhảy sau đây.Bàn cờ nhảy là một băng N ô mã số từ 1 đến N. Một quân cờ @ được đặt tại một ô x nào đó trên bàn cờ. Cho trước hai giá trị M trong khoảng 1 N và y trong khoảng 1 M. Hai đấu thủ là A và B lần lượt di chuyển quân cờ. Luật chơi như sau:• Đến lượt ai, người đó nhiệm vụ di chuyển quân cờ thêm t ô với t nằm trong khoảng 1 ≤ t ≤ M, nhưng không được phép chọn trùng với số t của người vừa đi,• A luôn đi trước trong mọi ván cờtrong nước đi đầu tiên của mình A phải chọn t ≠ y,• Nếu ai không cách nào di chuyển quân cờ thì sẽ thua. Ván cờ kết thúc.Yêu cầu: Hãy cho biết A thể thắng hay không? Trong trường hợp A thắng, hãy cho biết A thể thắng sau tối đa bao nhiêu nước đi với giả thiết là hai đấu thủ A và B đều chơi rất giỏi và mỗi lượt A hoặc B đi được gọi là một nước đi.Thí dụ trên Hình 3, với N = 15, nếu ta quy định M = 4, x = 8, y = 2 thì A sẽ thua. Ngược lại, nếu ta quy định M = 4, x = 9, y = 3 thì A sẽ thắng sau 3 nước đi.Gợi ý: Bạn hãy coi cờ nhảy chính là cờ bảng với 4 giá trị N, M, x và y. Do đó, trước hết bạn phải giải cờ bảng rồi sau đó mới chuyển cách đi qua cờ nhảy . nước đi.Thí dụ: Bài giảiĐây là một bài toán khó thuộc lớp các bài toán trò chơi, tuy nhiên lời giải là dễ hiểu và đặc biệt là thuật giải bài toán này có thể. Ngày xuân lập trình chơi cờ bảngNguyễn Xuân HuyBài toán Tab game (Cờ bảng )Cờ bảng gồm một bảng N x M ô vuông đơn vị và một quân cờ kí hiệu là @. Các dòng

Ngày đăng: 07/09/2012, 10:30

HÌNH ẢNH LIÊN QUAN

• N- số lượng dòng của bảng, s≤ 200, • M - số lượng cột của bảng, 1 ≤ s ≤ 50, • x - tọa độ dòng xuất phát của quân cờ, • y - tọa độ cột xuất phát của quân cờ - Bài toán chơi cờ trong Pascal
s ố lượng dòng của bảng, s≤ 200, • M - số lượng cột của bảng, 1 ≤ s ≤ 50, • x - tọa độ dòng xuất phát của quân cờ, • y - tọa độ cột xuất phát của quân cờ (Trang 2)
Lần lượt điền các giá trị và 1 vào các ô trong từng dòng của bảng, theo trật tự từ dòng cao nhất, dòng thứ N đến dòng thấp nhất, dòng 1 - Bài toán chơi cờ trong Pascal
n lượt điền các giá trị và 1 vào các ô trong từng dòng của bảng, theo trật tự từ dòng cao nhất, dòng thứ N đến dòng thấp nhất, dòng 1 (Trang 3)
Thí dụ trên Hình 3, với N= 15, nếu ta quy định M= 4, x= 8 ,y =2 thì A sẽ thua.Ngược lại, nếu ta quy định M = 4, x = 9, y = 3 thì A sẽ thắng sau 3 nước đi. - Bài toán chơi cờ trong Pascal
h í dụ trên Hình 3, với N= 15, nếu ta quy định M= 4, x= 8 ,y =2 thì A sẽ thua.Ngược lại, nếu ta quy định M = 4, x = 9, y = 3 thì A sẽ thắng sau 3 nước đi (Trang 8)

TỪ KHÓA LIÊN QUAN

w