Thứ Năm, 27 tháng 11, 2014

Mảng 2 chiều - Xoắn ốc

Thuật toán gán các số tự nhiên liên tiếp vào mảng 2 chiều theo hình xoáy trôn ốc:
1. Sử dụng mảng có kích thước N+2 (bao gồm các biên ảo ở bốn phía). Khởi tạo mảng gồm toàn các số 0, riêng các giá trị chặn ở biên của mảng thì gán 1
2. Bắt đầu gán từ số 1 (i=1), vị trí bắt đầu là hàng 1, cột 0, hướng sang phải
3. Từ vị trí hiện tại, nếu tiếp tục đi theo hướng đang sử dụng sẽ gặp một ô có giá trị khác 0 (là ô đã được gán giá trị hoặc là ô chặn biên), thì đổi hướng theo vòng tròn như sau: sang phải -> xuống dưới -> sang trái -> lên trên -> lặp lại sang phải
4. Chuyển hướng di chuyển theo (3) nếu phải chuyển hướng, đi theo hướng lựa chọn 1 ô, gán giá trị i vào ô đó, tăng i lên 1 đơn vị
5. Vòng lặp dừng khi i=NxN

Bài ví dụ:

const
    dir: array [0..3, 1..2] of shortint = ((0,1), (1,0), (0,-1), (-1,0)); { 4 hướng di chuyển }
var
    a: array [0..20, 0..20] of integer;
    i, n: integer;
    x, y, d: integer;
begin
    write('Nhap N = '); readln(n);
    { khởi tạo mảng a }
    fillchar(a, sizeof(a), 0); { khởi tạo mảng a gồm toàn số 0 }
    a[1,n+1]:=1; a[n+1,n]:=1; a[n,0]:=1; a[0,1]:=1; { giá trị biên }
    { tạo ma trận }
    y:=1; x:=0; d:=0; { vị trí và hướng bắt đầu }
    for i:=1 to n*n do
    begin
        if a[y+dir[d,1], x+dir[d,2]] <> 0 then d:=(d+1) mod 4; { đổi hướng }
        y:=y+dir[d,1];
        x:=x+dir[d,2];
        a[y,x]:=i;
    end;
    { in ra ma trận }
    for y:=1 to n do
    begin
        for x:=1 to n do write(a[y,x]:4);
        writeln;
    end;
    readln;
end.


Chú ý:
1. Mảng dir: array [0..3, 1..2] chứa 4 véctơ tương ứng với 4 hướng di chuyển sang phải, xuống dưới, sang trái và lên trên - dùng để di chuyển trong mảng 2 chiều A
2. Hàm fillchar dùng để gán hàng loạt giá trị 0 vào mảng A, có thể thay bằng vòng lặp duyệt toàn mảng A và gán giá trị 0
3. a[1,n+1]:=1; a[n+1,n]:=1; a[n,0]:=1; a[0,1]:=1; là 4 ô chặn 4 hướng di chuyển đầu tiên để tạo thành vòng ngoài cùng của hình xoáy trôn ốc
4. if a[y+dir[d,1], x+dir[d,2]] <> 0 then d:=(d+1) mod 4; Kiểm tra nếu như đi theo hướng hiện tại gặp 1 ô đã gán giá trị (hay gặp 1 ô chặn) thì đổi sang hướng kế tiếp
5. Để in cho đẹp với màn hình 80 cột thì chỉ nên nhập các giá trị N<=19

1 nhận xét:

  1. đưa thêm lệnh nếu n là số chẵn thì mời nhập lại thì làm thế nào ạ và bỏ ở chỗ nào ạ

    Trả lờiXóa