Trong bài toán Josephus, một nhóm binh sĩ bị kẻ thù bao vây và một binh sĩ được chọn để đi cầu cứu. Việc chọn thực hiện theo cách sau:
Tài liệu: Docs.vn Hỗ trợ : Y!M minhu888 Trường Đại học Công Nghệ Thông Tin Đại học Quốc gia Hồ Chí Minh Bộ môn: Phương pháp luận sáng tạo khoa học Bài luận : Trình bày nội dung vận dụng kiến thức phương pháp luận, sáng tạo để giải vấn đề tin học GVHD: GS.TSKH Hoàng Văn Kiếm Sinh viên: Nghiêm Xuân Hiệp MSSV: 06520155 Khoa: MMT&TT 01 Tài liệu: Docs.vn Hỗ trợ : Y!M minhu888 I Bài toán : Trong tốn Josephus, nhóm binh sĩ bị kẻ thù bao vây binh sĩ chọn để cầu cứu Việc chọn thực theo cách sau: Một số nguyên n binh sĩ chọn cách ngẫu nhiên Các binh sĩ xếp theo vòng tròn, họ đếm binh sĩ chọn ngẫu nhiên Khi đạt đến n, binh sĩ tương ứng lấy khỏi vòng việc đếm lại binh sĩ Quá trình tiếp tục lại binh sĩ Đó người chọn để cầu cứu Viết thuật toán cài đặt cách chọn tìm binh sĩ chọn Tài liệu: Docs.vn Hỗ trợ : Y!M minhu888 II Giải toán: Phân tích tốn: Binh sĩ Binh sĩ Binh sĩ Binh sĩ Binh sĩ m Binh sĩ Binh sĩ Binh sĩ … Binh sĩ Các binh sĩ xếp đứng thành vịng trịn có thứ tự từ đến m (với m số binh sĩ) Tài liệu: Docs.vn Hỗ trợ : Y!M minhu888 Binh Binh sĩ sĩ Binh sĩ 2 Binh sĩ thứ chọn ngẫu nhiên Binh sĩ Binh sĩ thứ bị loại sau đếm đến n Binh sĩ Chọn n = Binh sĩ m Binh sĩ Binh sĩ … Binh sĩ thứ bị loại sau đếm đến n Binh sĩ Binh sĩ : Binh sĩ thứ n bị loại Chọn n số ngẫu nhiên chọn binh sĩ ngẫu nhiên (n nguyên dương) Tài liệu: Docs.vn Hỗ trợ : Y!M minhu888 - Chọn n số ngẫu nhiên chọn binh sĩ ngẫu nhiên (n nguyên dương) - Đếm từ vị trí binh sĩ ngẫu nhiên chọn vị trí binh sĩ thứ n loại binh sĩ ra, tiếp tục đếm từ binh sĩ vị trí thứ n - Khi binh sĩ người cuối lại người chọn để cầu cứu Giải vấn đề - toán tin học: Đối với toán này, điều ta quan tâm số lượng binh sĩ, số thứ tự binh sĩ, số thứ tự binh sĩ chọn, số n nguyên dương ngẫu nhiên với điều kiện n phải nhỏ số lượng binh sĩ, cuối tìm phần tử (binh sĩ) cuối Dùng phương pháp trực tiếp với nguyên lý, nguyên tắc để giải toán - Đặc điểm cách giải xác định trực tiếp lời giải qua thủ tục tính tốn (cơng thức, hệ thức, định luật,…) qua bước để có lời giải Đối với phương pháp này, việc giải tốn máy tính thao tác lập trình chuyển đổi lời giải từ ngơn ngữ bên ngồi sang ngơn ngữ sử dụng máy tính - Với tốn này, ta dùng ngơn ngữ lập trình thơng dụng C để giải toán máy tính Để thực tốt phương pháp trực tiếp, áp dụng nguyên lý sau: a) Nguyên lý 1: Chuyển đổi liệu toán thành liệu chương trình, có nghĩa “Dữ liệu toán biểu diễn lại dạng Tài liệu: Docs.vn Hỗ trợ : Y!M minhu888 biến chương trình thơng qua quy tắc xác định ngơn ngữ lập trình” • Gọi số lượng binh sĩ : m • Số thứ tự (vị trí) binh sĩ : biểu diễn dạng danh sách ta phân tích Trong binh sĩ phần tử element_type số thứ tự đại diện cho element_type • Số thứ tự binh sĩ chọn ngẫu nhiên : k • Một số đếm n ngẫu nhiên : n • Phần tử cuối chọn danh sách binh sĩ chọn : element • m, k, n, element_type, element số nguyên dương b) Nguyên lý 2: Chuyển đổi q trình tính tốn tốn thành cấu trúc chương trình, có nghĩa “Mọi q trình tính tốn mơ tả thực dựa ba cấu trúc bản: Cấu trúc tuần tự, cấu trúc rẽ nhánh cấu trúc lặp” - Ở ta sử dụng cấu trúc tuần tự: để biểu diễn phần tử (binh sĩ) ta dùng list (danh sách) dạng : node - Trong node ta quan tâm đến phần tử phần tử cuối cùng: first last first (element_type) next (element_type) Cấu trúc node last (element_type) Tài liệu: Docs.vn Hỗ trợ : Y!M minhu888 c) Nguyên lý : Phân chia toán đầu thành toán nhỏ hơn, có nghĩa “Mọi vấn đề tốn giải cách phân chia thành vấn đề toán nhỏ hơn” - Đối với toán việc phân nhỏ toán thành phần (thành hàm) thay xử lý chúng hàm void() cần thiết có ý nghĩa mặt trình bày đoạn code dễ nhìn mà cịn có nhiều ý nghĩa khác kể việc sữa chữa cách dễ dàng o void khoi_tao_ds(struct node **first, struct node **last) o void insert( element_type e, struct node **first, struct node **last) o void xoa_ds( struct node **first, struct node ** last) o void tao_ds( struct node **first, struct node **last, int n) o void print_ds( struct node *first) o void Josephus( struct node **first, struct node ** last, int m, int n, int k) o void main() d) Nguyên lý 3: Biểu diễn tính tốn xác, có nghĩa “Chương trình tính tốn theo biểu thức xác khơng đồng với q trình tính tốn xác mặt hình thức” Thay thực tế người đếm loại dần binh sĩ thứ n lại binh sĩ cuối cùng, ta thấy hàm Josephus chạy vòng lặp (cho đến m = 1) so sánh điều kiện để cuối tìm phần tử cịn lại Tài liệu: Docs.vn Hỗ trợ : Y!M minhu888 void Josephus( struct node **first, struct node **last, int n, int m, int k) { struct node *tmp, *b; int i; tmp = *first; for( i = 0; i next; do{ for(i = 0; i next != NULL) tmp = tmp -> next; else tmp = *first; if( tmp ->next == NULL) { tmp = (*first) -> next; free(first); *first = tmp; } else { b = tmp -> next; if( tmp -> next -> next != NULL) { tmp -> next = tmp -> next -> next; tmp = tmp -> next; } else { tmp -> next = NULL; tmp = *first; } free(b); // xoa node b } m ; // giam so luong phan tu di }while( m>1); // chay vong lap cho den m = *last = *first; // gan phan tu lai cuoi cung cho //tro **first } Tài liệu: Docs.vn Hỗ trợ : Y!M minhu888 e) Nguyên tắc trung gian : - Sử dụng đối tượng trung gian, chuyển tiếp - Trong nhiều chương trình máy tính, người ta viết biểu thức tính tốn phức tạp hàng Điều chẳng ảnh hưởng đến kết tính tốn cuối làm cho việc đọc biểu thức trở lên khó khăn Trong trường hợp ta dùng biến trung gian để làm cho chương trình dễ hiểu - Ở ta thấy hàm print_ds() sử dụng phần tử node trung gian tmp để duyệt danh sách in phần tử void print_ds(struct node **first) { struct node *tmp; // su dung node trung gian tmp de duyet tmp = first; // gan tmp tai vi tri phan tu dau tien printf(“Cac gia tri cua danh sach: ”); while( tmp != NULL) // duyet danh sach va in cac phan tu cho { // den het danh sach printf(“%d”, tmp ->element); // in so thu tu cac tmp = tmp -> next; // phan tu } } f) Nguyên tắc chứa : - Một đối tượng đặt bên đối tượng khác thân lại chứa đối tượng thứ ba… - Một đối tượng chuyển động xuyên suốt bên đối tượng khác - Trong tin học, chương trình chứa nhiều chương trình Trong chương trình lại chứa nhiều chương trình khác Ở ta thấy danh sách node chẳng qua trỏ (node *next) chạy suốt trỏ đến mảng phần tử (element_type), hay nói next đối tượng chuyển động xuyên suốt bên danh sách node Tài liệu: Docs.vn Hỗ trợ : Y!M minhu888 Code tốn Josephus hồn chỉnh : #include typedef int element_type; struct node { element_type element; struct node *next; }; void khoi_tao_ds(struct node **first, struct node ** last) { *first = *last = NULL; } void insert(element_type e, struct node **first, struct node **last) { struct node *tmp; tmp = (struct node*) malloc(sizeof(struct node)); tmp -> element = e; tmp -> next = NULL; if(*first == NULL) *first = *last = tmp; else { (*last) -> = tmp; (*last) = (*last) -> next; } } void xoa_ds(struct node **first, struct node **last) { struct node *tmp; Tài liệu: Docs.vn Hỗ trợ : Y!M minhu888 tmp = *first; while( tmp != NULL) { tmp = (*first) -> next; free(*first); *first = tmp; } *first = *last = NULL; } void tao_ds( struct node **first, struct node **last, int n) { element_type e; for ( e=0; eelement); tmp = tmp -> next; } } void Josephus( struct node **first, struct node **last, int n, int m, int k) { struct node *tmp, *b; int i; tmp = *first; for( i = 0; i next; do{ for(i = 0; i next != NULL) tmp = tmp -> next; Tài liệu: Docs.vn Hỗ trợ : Y!M minhu888 else tmp = *first; if( tmp ->next == NULL) { tmp = (*first) -> next; free(first); *first = tmp; } else { b = tmp -> next; if( tmp -> next -> next != NULL) { tmp -> next = tmp -> next -> next; tmp = tmp -> next; } else { tmp -> next = NULL; tmp = *first; } free(b); } m ; }while( m>1); *last = *first; } void main() { struct node *first; int n,m,k; khoi_tao_ds(&first, &last); printf(“\nCho biet so luong binh si: ”); scanf(“%d“, &m); tao_ds(&first, &last, m); print_ds(first); printf(“\nCho biet so thu tu binh si duoc chon: ”); scanf(“%d”, &k); Tài liệu: Docs.vn Hỗ trợ : Y!M minhu888 printf(“\nCho biet gia tri dem: ”); scanf(“%d”, &n); Josephus(&first, &last, m, n, k); printf(“\nNguoi duoc chon co thu tu la : %d”, first -> element); xoa_ds(&first, &last); getch(); } ... Dùng phương pháp trực tiếp với nguyên lý, nguyên tắc để giải toán - Đặc điểm cách giải xác định trực tiếp lời giải qua thủ tục tính tốn (cơng thức, hệ thức, định luật,…) qua bước để có lời giải. .. phương pháp này, việc giải toán máy tính thao tác lập trình chuyển đổi lời giải từ ngôn ngữ bên ngồi sang ngơn ngữ sử dụng máy tính - Với tốn này, ta dùng ngơn ngữ lập trình thơng dụng C để giải. .. nghĩa “Mọi vấn đề tốn giải cách phân chia thành vấn đề toán nhỏ hơn” - Đối với toán việc phân nhỏ tốn thành phần (thành hàm) thay xử lý chúng hàm void() cần thiết khơng có ý nghĩa mặt trình bày đoạn