Hotline: 024.62511017

024.62511081

  Trang chủ   Sản phẩm   Phần mềm Dành cho nhà trường   Phần mềm Hỗ trợ học tập   Kho phần mềm   Liên hệ   Đăng nhập | Đăng ký

Tìm kiếm

School@net
 
Xem bài viết theo các chủ đề hiện có
  • Hoạt động của công ty (726 bài viết)
  • Hỗ trợ khách hàng (498 bài viết)
  • Thông tin tuyển dụng (57 bài viết)
  • Thông tin khuyến mại (80 bài viết)
  • Sản phẩm mới (216 bài viết)
  • Dành cho Giáo viên (549 bài viết)
  • Lập trình Scratch (3 bài viết)
  • Mô hình & Giải pháp (156 bài viết)
  • IQB và mô hình Ngân hàng đề kiểm tra (127 bài viết)
  • TKB và bài toán xếp Thời khóa biểu (242 bài viết)
  • Học tiếng Việt (183 bài viết)
  • Download - Archive- Update (289 bài viết)
  • Các Website hữu ích (70 bài viết)
  • Cùng học (92 bài viết)
  • Learning Math: Tin học hỗ trợ học Toán trong nhà trường (78 bài viết)
  • School@net 15 năm (154 bài viết)
  • Mỗi ngày một phần mềm (7 bài viết)
  • Dành cho cha mẹ học sinh (124 bài viết)
  • Khám phá phần mềm (122 bài viết)
  • GeoMath: Giải pháp hỗ trợ học dạy môn Toán trong trường phổ thông (36 bài viết)
  • Phần mềm cho em (13 bài viết)
  • ĐỐ VUI - THƯ GIÃN (363 bài viết)
  • Các vấn đề giáo dục (1210 bài viết)
  • Bài học trực tuyến (1037 bài viết)
  • Hoàng Sa - Trường Sa (17 bài viết)
  • Vui học đường (275 bài viết)
  • Tin học và Toán học (220 bài viết)
  • Truyện cổ tích - Truyện thiếu nhi (180 bài viết)
  • Việt Nam - 4000 năm lịch sử (97 bài viết)
  • Xem toàn bộ bài viết (8223 bài viết)
  •  
    Đăng nhập/Đăng ký
    Bí danh
    Mật khẩu
    Mã kiểm traMã kiểm tra
    Lặp lại mã kiểm tra
    Ghi nhớ
     
    Quên mật khẩu | Đăng ký mới
     
    Thành viên có mặt
    Khách: 12
    Thành viên: 0
    Tổng cộng: 12
     
    Số người truy cập
    Hiện đã có 89598465 lượt người đến thăm trang Web của chúng tôi.

    Chia sẻ một thuật toán hay

    Ngày gửi bài: 24/12/2005
    Số lượt đọc: 19183

    Trong rất nhiều bài toán khi đọc lên yêu cầu ta đều có ngay thuật toán để giải quyết nó, song các thuật toán phát sinh đó nếu không phân tích kĩ và tinh tế nhận dạng thì chỉ giải quyết được khi kích cỡ dữ liệu đầu vào là khá nhỏ có nghĩa là chỉ giải quyết được bài toán trong những trường hợp rất hạn chế. Trong lớp các bài toán như vậy ở đây tôi xin giới thiệu một số bài toán khác nhau song cách giải quyết lại khá giống nhau.

    Bài toán 1:

    Cho file văn bản gồm rất nhiều dòng, mỗi dòng 80 kí tự. Các kí tự của file văn bản gồm “*” và “.” Các kí tự “*” trong văn bản tạo nên các chữ cái T,E,F,I. hãy đếm các số lượng các chữ cái T,E,F,I có trong văn bản giả sử dữ liệu vào là đúng.

    Ví dụ file input như sau:

    ……….********…………*……..*************…………*********
    ……….*…………………..*…………….*…………………*…………..
    ……….*******....………..*…………….*………******….******…..
    ……….*………………….........................*…………*……..*…………..
    ……….*…...…………………………………………*……..**********

    Thì có 2 chữ T,1 chữ E, 1 chữ F, và 1 chữ I.

    Bài toán 2:

    Bài toán tương tự mà tôi muốn giới thiệu ở đây là bài toán trong kì thi OLIMPIC Tin học Sinh viên Việt Nam lần thứ 14 năm 2005 tại TP.Hồ Chí Minh vừa qua. Đây là bài toán không khó, nhưng để vượt qua hết test của BGK lại là một điều không dễ. Bài toán đại ý như sau:

    Ảnh chụp mặt người sau khi đã xử lý là 1 bảng vuông A kích thước NxN (10 < N < 800). Với mỗi ô (i,j) có giá trị từ 0 đến 255 là mức xám của ảnh tại ô này (trong đó 0 là màu nền). Để xác định vị trí là mặt người, ta cần thống kê các đặc trưng có dạng hình vuông kích thước k x k (1 < K ≤ 40) trong đó các giá trị trong hình vuông đều phải khác 0.

    Yêu cầu : Từ 1 ảnh chụp mặt người đếm tất cả các đặc trưng có trong ảnh đó.

    3. Cách giải quyết.

    Với bài toán thứ nhất ta thấy rằng việc đọc dữ liệu vào một mảng 2 chiều là điều không thể, vì không biết trước số dòng của văn bản sẽ là bao nhiêu? bộ nhớ có đủ chỗ hay không? Mà nếu có đọc được đi chăng nữa thi chắc gì đã có cách nào hay để giải! Ta hãy đi tìm các đặc trưng của các chữ T,E,F,I. Ta thấy rằng các chữ cái này đều có 1 trục thẳng đứng. Cụ thể với chữ I có 1 trục thẳng không có gạch nằm ngang nào, với chữ T có 1 gạch nằm ngang, chữ F có 2 gạch nằm ngang, chữ E có 3 gạch… như vậy chữ I có 1 nét, chữ T có 2 nét, chữ F có 3 nét và chữ E có 4 nét. Ta sẽ đếm số nét của chữ để xác định đó là chữ gì!

    Để đếm các nét của chữ ta sử dụng 1 mảng 1 chiều d[1..80], ban đầu ta clear các giá trị của mảng này=0, ta sử dụng 1 mảng dem[1..4] để đếm số lượng các chữ cái, trong đó dem[1] là số lượng chữ I, dem[2] là số lượng chữ T, dem[3] là số lượng chữ F và dem[4] là số lượng chữ E. Ta sẽ xử lý 2 dòng (st1,st2) liền nhau trong văn bản:

    Ta xét các trường hợp sau:

    1.(St1[i]=’*’^st1[i+1]=’*’^St2[i]=’*’^st2[i+1]=’.’)->d[i]:=d[i]+1
    2.(St1[i-1]=’.’^St1[i]=’*’^st1[i+1]=’*’^St2[i]=’.’^d[i]<>0)->d[i]:=d[i]+2;
    3.(St1[i-1]=’.’^St1[i]=’*’^st1[i+1]=’.’^St2[i]=’.’) -> d[i]:=d[i]+1

    Trường hợp 2 và 3 là các trường hợp kết thúc của 1 chữ cái, do vậy ta sẽ tăng dem[d[i]] lên 1 trong các trường hợp đó, đồng thời d[i]:=0;Cứ như vậy cho đến khi kết thúc file và giá trị của dem[1..4] sẽ cho ta số lượng các chữ I,T,F,E đếm được. Phải chú ý rằng khi đọc hết file input thì st1 chứa dòng cuối cùng và st2 chứa 1 chuỗi các kí tự ‘.’ để xét lần cuối cùng. Như vậy bài toán 1 đã được giải quyết.

    Với bài toán thứ 2: Cách đơn giản nhất mà ta nghĩ đến khi đọc đề bài có thể là cách áp tất cả các hình vuông KxK lên bảng vuông NxN rồi xét và đếm. cách tốt hơn nữa là trước khi áp hình vuông ta có thể đánh dấu các ô có giá trị 0 và các ô nằm trên cùng 1 hình vuông KxK với ô đó, và cách tốt hơn cách này nữa là hình vuông kế tiếp được xét bằng cách bớt cột bên trái thêm cột bên phải, hoặc bớt hàng bên trên thêm hàng bên dưới như vậy ta chỉ cần xét trên các cột thêm hoặc hàng thêm này mà thôi…song chúng ta phải chú ý rằng bài này đòi hỏi chạy trong 2 giây và dữ liệu tối đa là 800x800. Thực tế dữ liệu 800x800 đã là 1 gợi ý của bài toán để chúng ta biết rằng không thể đọc toàn bộ bảng vuông vào mảng 2 chiều được, nhưng như vậy lại có bạn đọc từng phần 1 để xử lý, tuy nhiên nếu thế lại không đáp ứng được thời gian chạy của chương trình.Và cách giải quyết ở đây là hoàn toàn đơn giản, chúng ta áp dụng như các giải quyết của bài TEFI ở trên.

    Như vậy ta sẽ đọc từng dòng của bảng A vào chuỗi st và sử dụng mảng d[1..801] (phần tử thứ 801 dùng làm lính canh) kiểu word để xử lý. Giá trị d[i] sẽ là số các ô khác 0 liên tục tính từ dòng đang xét trở lên ở cột i của bảng A. Ban đầu ta clear các gía trị của mảng d[1..801].

    //Khởi tạo ban đầu

    Procedure Khoitao;
    begin
    Fillchar(a,sizeof(d),0);
    dem:=0;
    d[n+1]:=0;//phàn tử lính canh
    end;
    //Xử lý dữ liệu đọc vào
    Procedure Xuly;
    Var x,j,i : word;
    Begin
    Assign(f,’xulyanh.out’);
    Reset(f);
    For j:=1 to n do
    Begin
    For i:= 1 to n do
    Read(f,x);
    If x<>0 then inc(d[i])
    Else d[i]:=0;
    End;
    If j>=k then Duyet;
    readln(f);
    End;
    Close(f);
    End;
    //Xử lý mảng trên d được viết như sau:
    Procedure Duyet;
    Var j,i : word;
    Begin
    For i:= 1 to n-k do
    Begin
    J:=0;
    While (d[i+j]>k ) and (j<=k) do inc(j);
    If j>k then inc(dem);
    End;
    End;

    Xử lý dữ liệu trên mảng d theo cách viết trên là chưa tối ưu, chỉ mang tính mô tả để ta dễ hiểu cách làm. Ta nên viết lại Procedure Duyet như sau:

    Procedure Duyet;
    Var j,i : word;
    Begin
    i:=1;
    Repeat
    While d[i] < k do inc(i);
    if i < n-k then
    Begin
    j:=0;
    While (d[i+j]>=k) and (j<=k) do inc(j);
    if j>k then
    Begin
    inc(dem); i:=i+k+1;
    while (d[i]>=k) do
    Begin
    inc(i);
    inc(dem);
    End;
    End
    Else i:=i+j;
    End;
    Until i>n-k
    End;

    Thoát khỏi vòng lặp này biến dem sẽ trả về số các đặc trưng tìm thấy của ảnh! Như vậy bài toán đã được giải quyết 1 cách trọn vẹn.

    4. Bài toán mở rộng.

    1. Cho file văn bản chứa các kí tự ‘0’ và ‘1’ file gồm rất nhiều dòng, mỗi dòng có 1000 kí tự. Hãy xác định toạ độ hình vuông lớn nhất trong văn bản chỉ chứa hoặc là kí tự ‘0’ hoặc là kí tự ‘1’. Yêu cầu đưa ra toạ độ đầu và độ dài của cạnh hình vuông tìm được.

    2. Quay lại bài toán 1 nếu các chữ cái T,E,F,I của chúng ta có thể quay 900,1800, 2700 thì chúng ta sẽ đếm các chữ cái này như thế nào?

    Xin hẹn các bạn ở một bài toán khác. Mọi góp ý, trao đổi xin liên hệ qua email duyhaman@yahoo.com.. Xin chân thành cảm ơn!

    Nguyễn Duy Hàm (Theo Tạp chí TH&NT)



     Bản để in  Lưu dạng file  Gửi tin qua email


    Những bài viết khác:



    Lên đầu trang

     
    CÔNG TY CÔNG NGHỆ TIN HỌC NHÀ TRƯỜNG
     
    Phòng 804 - Nhà 17T1 - Khu Trung Hoà Nhân Chính - Quận Cầu Giấy - Hà Nội
    Phone: 024.62511017 - 024.62511081
    Email: kinhdoanh@schoolnet.vn


    Bản quyền thông tin trên trang điện tử này thuộc về công ty School@net
    Ghi rõ nguồn www.vnschool.net khi bạn phát hành lại thông tin từ website này
    Site xây dựng trên cơ sở hệ thống NukeViet - phát triển từ PHP-Nuke, lưu hành theo giấy phép của GNU/GPL.