Thứ Hai, 16 tháng 12, 2013

Bốc sỏi F



Cho 2 đống sỏi với số viên sỏi lần lượt là N và M viên, N, M  > 1. Hai người chơi A và B, A luôn đi trước. Lượt chơi: Chọn đống tùy ý, bốc tối thiểu 1 viên và tối đa nửa số viên của đống. Đấu thủ nào đến lượt mình mà  không đi nổi thì thua. Hãy cho biết A thắng hay thua. Giả thiết rằng hai đấu thủ  đều chơi rất  giỏi.
Thuật toán
Mới xem ta thấy rằng bất biến thua cho bài này cũng là N = M. Dự đoán của bạn gần đúng vì N = M chỉ là một trường hợp đặc biệt của bất biến thua. Dễ thấy, nếu N = M =1 thì hết cách đi. Nếu N = M > 1 và A đi trước thì B chỉ việc cân bằng lại số sỏi của hai đống là chắc thắng. Vậy N = M là một điều kiện thua (cho người đi trước). 
Để lập bảng tính trị của hàm f(N,M) ta cũng nhận xét rằng hàm này đối xứng, tức là f(N,M) = f(M,N) vì trật tự của các đống sỏi là không quan trọng. Cũng chính vì f(N,M) là hàm đối xứng nên ta chỉ cần tính trị của f(N,M) với N £ M rồi lấy đối xứng qua đường chéo chính của bảng trị. Với mỗi N cho trước ta lần lượt điền từng dòng N của bảng với M = N, N+1, N+2,… Theo nhận xét trên ta có ngay f(N,N) = 0 với mọi N. Từ thế thua này ta thấy ngay f(N,N+d) = 1 với mọi d = 1,2,…N vì từ các thế này ta có thể bốc d viên từ đống thứ hai (đống có M=N+d viên) để dẫn đến thế thua f(N,N). Từ đây suy ra thế thua tiếp theo sẽ là f(N,N+N+1) = f(N,2N+1). Tương tự, thế thua tiếp sau thế này phải là f(N,2(2N+1)+1) = f(N,22N+2+1). Tổng qúat hóa ta thu được kết quả sau:
                Nếu đống sỏi thứ nhất có N viên thì các thế thua sẽ có dạng f(N,M) với M = 2kN+2k-1+…+2+1 = 2kN+(2k-1+…+2+1). Áp dụng công thức
2k-1 = (2-1)(2k-1+2k-2+…+2+1) = 2k-1+2k-2+…+2+1
ta thu được M = 2kN+2k-1 hay M+1 = 2k(N+1).
   Vậy
Bất biến thua  cho Bài Bốc sỏi F
Số sỏi trong hai đống thỏa hệ thức
(N+1) = 2k(M+1), k ³ 0   (*)
                Từ hệ thức (*) ta suy ra N = M là trường hợp riêng khi k = 0. 
                Hàm Ket và thủ tục CachDi khi đó sẽ như sau.
Để ý rằng các số nguyên trong máy tính được biểu diễn dưới dạng nhị phân nên giá trị 2k tương đương với toán tử dịch trái 1 k bit,  1 shl k.
function Ket(N,M : integer) : integer;
   var N1,M1,t: integer;
begin
    N1 := N+1; M1 := M+1;
  if N1 < M1 then
    begin
       t := N1; N1 := M1; M1 := t;
    end; { N1 ³ M1 }  
  while M1 < N1 do M1 := M1 shl 1; { 2*M1 }
  if (M1 = N1) then Ket := 0 else Ket := 1;
end;
Với thủ tục CachDi cho tình huống thua thì A đành bốc 1 viên ở đống nhiều sỏi. Trong trường hợp thắng ta cũng chọn đống nhiều sỏi để bốc bớt S viên sao cho số sỏi giữa hai đống thỏa hệ thức (*). Ta tính S như sau. Giả sử N > M và k là số nguyên đầu tiên thỏa hệ thức N+1  <  2k(M+1). Khi đó, do điều kiện thắng nên ta phải có 2k-1(M+1) < N+1 < 2k(M+1) . Vậy số sỏi chênh lệch cần bốc bớt ở đống nhiều sỏi sẽ là S = N+1-2k-1(M+1). Ta chứng minh rằng 1 £ S £ N/2. Thật vậy, vì 2k-1(M+1) < N+1 nên S = N+1-2k-1(M+1) ³ 1. Mặt khác, nếu S > N/2 thì 2S > N hay 2N+2-2k(M+1) > N. Từ đây rút ra N+1 >  2k(M+1)-1, hay N+1 ³  2k(M+1), mâu thuẫn với giả thiết về k.
procedure CachDi(N,M : integer; var D,S : integer);
    var N1,M1,t: integer;
begin
   { N = M = 1: dau hang }
   if (N = M) and (N = 1) then
    begin
       D := 0; S := 0;
       exit;
    end;
   { Chon dong nhieu soi }
   if N > M then D := 1 else D := 2;
   N1 := N+1; M1 := M+1;
   if N1 < M1 then
    begin
       t := N1; N1 := M1; M1 := t;
    end; { N1 ³ M1 }
   while M1 < N1 do M1 := M1 shl 1; { 2*M1 }
   if (M1 = N1) then { Thua }
      begin  { Se Thua }
         S := 1; { boc 1 vien }
         exit;
      end;
   { Cac tinh huong thang }
   M1 := M1 shr 1;
   S := N1-M1;
end; 

Nguồn:

SÁNG TẠO
TRONG THUẬT TOÁN
LẬP TRÌNH


Không có nhận xét nào:

Đăng nhận xét