# GÓC SÁNG TẠO > Khu vực lập trình > Pascal/Delphi/Kylix >  Sắp xếp ma trận hình xoắn ốc!

## ocean123

*Cho ma trận gồm n cột, n hàng nhập từ bàn phím. Với các giá trị của ma trận được sinh ngẫu nhiên trong khoảng (-200;200). Nhập thêm một số nguyên k (k>0)
Viết chương trình :
+ Sắp xếp ma trận này tăng dần theo chiều kim đồng hồ nếu k chẵn 
+ Sắp xếp ma trận này tăng dần ngược chiều kim đồng hồ nếu k lẻ*

----------


## hvdnghia3

sax! bài này là bài thi trong đề thi tin học trẻ không chuyên của khánh hòa của cấp 2.
Lần đó chưa đụng nên em mần ko dc. giải 2 bài xong bài thứ 3 là nó thì em ngồi xơi bút

----------


## fpicseo

Bạn nói đúng rồi đó. Đề này ra liền 2 năm liên tục. Các bạn cố gắng giải xem vài tuần nữa mình sẽ post bài giải.
Xin chào!

----------


## thienanphuoc01

đề bài này hay đấy

----------


## minhhai1307

Post đã lâu mà không ai giải.
Mình xin post bài giải :

Program MatranXoanoc;
Uses Crt;
Var A : Array[1..100,1..100] of Integer;
    B: Array[1..10000] Of Integer;
    I,J,Z,N,T,K,CD,CC,DD,DC : Integer;
(*====== Tao Mang =====*)
Procedure Taomang;
Begin
  Randomize;
  Write(' + Nhap N : '); Readln(N);
  z:=0;
  For i:=1 to N do
    For j:=1 to N do
    Begin
    A[i,j]:=Random(200)-Random(200);
    Inc(Z);
    B[Z]:=A[i,j];
    End;

  For i:=1 to Z do
    For j:=i to Z do
    If B_>B[j] Then
    Begin
      T:=B;
      B:=B[j];
      B[j]:=T;
    End;
End;
(*===== Xuat mang ======*)
Procedure Xuat;
Begin
 For i:=1 to N do
 Begin
  For j:=1 to N do
   Write(A[i,j]:5);
  Writeln;
 End;
End;
(*====== Sap xep Xoan Oc ======*)
Procedure Sapxep;
Begin
  Write(' Nhap K : '); Readln(K);
  CD:=1; DD:=1; CC:=N; DC:=N;
  j:=0;
  If K mod 2 = 0 Then
  Begin
    Writeln(' + Sap xep theo chieu Kim   dong ho ');
    Repeat
      For i:=CD to CC do
      Begin
        Inc(j);
        A[DD,i]:=B[j];
      End;
      For i:=DD+1 to DC do
      Begin
        Inc(j);
        A[i,CC]:=B[j];
      End;
      For i:=CC-1 downto CD do
      Begin
        Inc(j);
        A[DC,i]:=B[j];
      End;
      For i:=DC-1 downto DD+1 do
      Begin
        Inc(j);
        A[i,CD]:=B[j];
      End;
      Inc(CD); Inc(DD);
      Dec(CC); Dec(DC);
    Until j>=z;
  End Else
  Begin
    Writeln(' + Sap xep nguoc chieu Kim  dong ho');
    Repeat
      For i:=DD to DC do
      Begin
        Inc(j);
        A[i,CD]:=B[j];
      End;
      For i:=CD+1 to CC do
      Begin
        Inc(j);
        A[CC,i]:=B[j];
      End;
      For i:=DC-1 downto DD do
      Begin
        Inc(j);
        A[i,CC]:=B[j];
      End;
      For i:=CC-1 downto CD+1 do
      Begin
        Inc(j);
        A[DD,i]:=B[j];
      End;
      Inc(CD); Inc(DD);
      Dec(CC); Dec(DC);
    Until j>=z;
  End;
End;
(*===== Chuong Trinh Chinh =====*);
Begin
  Clrscr;
  Writeln(' CHUONG TRINH SAP XEP MA TRAN   XOAN OC');
  Writeln(' Mang duoc tao : ');
  Taomang;
  Xuat;
  Sapxep;
  Xuat;
  Readln;
End._

----------


## nguyencuong880

Cách giải của bạn quá dòng đợi mình rãnh mình post lên cho

----------


## huong2211hd

bài này ngó thế nhưng rắc rối thí mồ

----------


## vipcuchuoi02

Bạn có thể nêu thuật toán ko??? Chứ nhìn vào code thì khó hiểu quá.

----------


## 513minh89

Thuật toán rất đơn giản.
Bạn biến ma trận thành mảng 1 chiều rồi sắp xếp nó.
Nếu k chẵn sắp xếp theo chiều kim đồng hồ thì bạn duyệt mảng theo hình xoắn ốc rồi đưa các phần tử của mảng 1 chiều đã sắp xếp vào.
Với k lẻ thì tương tự.

----------


## virus

```
const fi='XOANXOAN.INP';
      fo='XOANXOAN.OUT';
var f:text;
    n,k,huong:longint;
    a:array[1..100,1..100] of longint;
procedure docfile;
begin
   assign(f,fi);
   reset(f);
   readln(f,n,k);
   close(f);
end;

procedure move(x,y:longint;var i,j:longint);
begin
   i:=x;j:=y;
   case huong of
      1:dec(i);
      2:inc(j);
      3:inc(i);
      4:dec(j);
      end;
end;

procedure xuly;
var i,j,x,y,d:longint;
begin
   if k mod 2 = 0 then
      begin
         huong:=2;k:=1;
      end
   else
      begin
         huong:=3;k:=-1;
      end;
   x:=1;y:=1;
   a[1,1]:=1;
   d:=1;
   repeat
      move(x,y,i,j);
      if (i=0) or (j=0) or (i>n) or (j>n) or (a[i,j]<>0) then
         begin
            inc(huong,k);
            if huong=5 then huong:=1
            else if huong=0 then huong:=4;
         end
      else if a[i,j]=0 then
         begin
            inc(d);
            a[i,j]:=d;
            x:=i;y:=j;
         end;
   until d=n*n;
end;

procedure ghifile;
var i,j:longint;
begin
   assign(f,fo);
   rewrite(f);
   for i:=1 to n do
      begin
         for j:=1 to n do write(f,a[i,j],' ');
         writeln(f);
      end;
   close(f);
end;

begin
   docfile;
   xuly;
   ghifile;
end.
```

cách của mình đây, 
mình ngán sắp xếp nên in ra mảng theo tứ tự từ 1 đến n*n nhe !!!
[IMG]data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAA  l21bKAAAAA1BMVEXh5PJm+yKVAAAAAXRSTlMAQObYZgAAAApJR  EFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=[/IMG] bạn nào thích cách này thanks mình cái nhe, lấy khí thế

----------


## sonseo9x5s

lôi bài từ cái đời nào ra làm =.=! RẢNH HỠ

----------


## BRASOL

tại bài này nghe đề lâu rồi mà chưa làm ( mình mắc bệnh lười cấp + mãn tính )
hum qua có vài ý tưởng mới nên code thử

----------


## tvintec

ý tưởng của mình thế này :
tạo thành hình xoắn ốc thì mình cứ đi thẳng đi, rồi gặp viền hay những ô đã được điền rồi thì rẽ, cho đến khi điền đủ n*n số thì thôi

hướng mình gọi theo số, hướng bắc số 1; hướng đông số 2; hướng nam số 3; hướng tây số 4;

nếu xoắn theo chiều kim đồng hồ thì hướng xuất phát là 2 (huong:=2) và khi rẽ thì rẽ sang hướng (huong+1), nếu huong=5 thì sửa lại huong=1;
nếu xoắn theo chiều ngụơc chiều kim đồng hồ thì tương tự thôi

----------


## kimdung01

Em tìm ra công thức nào mà không cần phải dài dòng, chỉ cần cho i chạy nhưng vẫn sắp xếp vào mảng theo hình xoắn ốc không?! [IMG]data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAA  l21bKAAAAA1BMVEXh5PJm+yKVAAAAAXRSTlMAQObYZgAAAApJR  EFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=[/IMG]
*Max i* là chiều dài của cạnh hình vuông đó.

----------


## Nam An Tam

```
const fi='XOANXOAN.INP';
      fo='XOANXOAN.OUT';
      tdi:array[1..4] of shortint = (-1,0,1,0);
      tdj:array[1..4] of shortint = (0,1,0,-1);
var f:text;
    n,k,huong:longint;
    a:array[1..100,1..100] of longint;
procedure docfile;
begin
   assign(f,fi);
   reset(f);
   readln(f,n,k);
   close(f);
end;

procedure xuly;
var i,j,x,y,d:longint;
begin
   x:=1;y:=1;
   a[1,1]:=1;
   d:=1;huong:=2;
   repeat
      i:=x+tdi[huong];j:=y+tdj[huong];
      if (i=0) or (j=0) or (i>n) or (j>n) or (a[i,j]<>0) then
         begin
            inc(huong);
            if huong=5 then huong:=1
            else if huong=0 then huong:=4;
         end
      else if a[i,j]=0 then
         begin
            inc(d);
            a[i,j]:=d;
            x:=i;y:=j;
         end;
   until d=n*n;
end;

procedure ghifile;
var i,j:longint;
begin
   assign(f,fo);
   rewrite(f);
   if k mod 2 = 0 then
      for i:=1 to n do
         begin
            for j:=1 to n do write(f,a[i,j],' ');
            writeln(f);
         end
   else
      for j:=1 to n do
         begin
            for i:=1 to n do write(f,a[i,j],' ');
            writeln(f);
         end;
   close(f);
end;

begin
   docfile;
   xuly;
   ghifile;
end.
```

em làm thế này là ngắn hết mức có thể ( với em ) rồi đó
anh caodai...... tìm giúp em công thức mà không cần phải dài dòng, chỉ cần cho i chạy nhưng vẫn sắp xếp vào mảng theo hình xoắn ốc nhe !!! [IMG]data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAA  l21bKAAAAA1BMVEXh5PJm+yKVAAAAAXRSTlMAQObYZgAAAApJR  EFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=[/IMG]

----------

