Phân tích bài toán và xây dựng thuật toán

Một phần của tài liệu Bài toán tìm bộ ghép cực đại trên đồ thị, ứng dụng giải một số bài toán trong thực tế (Trang 69 - 80)

CHƯƠNG 3. MỘT SỐ BÀI TOÁN ỨNG DỤNG TRONG THỰC TẾ

3.2 BÀI TOÁN XẾP LỚP HỌC THEO TÍN CHỈ

3.2.3 Phân tích bài toán và xây dựng thuật toán

Danh sách sinh viên giả thiết được cung cấp từ một chương trình quản l sinh viên (được lưu trong cơ sở dữ liệu), mỗi sinh viên mang một mã riêng theo quy định của nhà trường.

Danh sách các học phần của tất cả các ngành học cũng đã được lưu trong cơ sở dữ liệu, mỗi học phần mang một mã riêng theo quy định của nhà trường. Thông tin vào:

Các học phần giảng d y trong học kỳ.

Số lƣợng học phần mỗi sinh viên muốn học.

Danh sách các học phần c thể theo học của mỗi sinh viên.

(Giả sử với lựa chọn bất kỳ cho mỗi sinh viên, tổng số tín chỉ theo học của mỗi sinh viên không nằm ngoài giới hạn của nhà trường.) Thông tin ra:

Danh sách sinh viên theo học từng học phần.

Bài toán đƣợc giải quyết bằng thuật toán phỏng theo thuật toán Hung-ga-ri.

Thuật toán:

Bước 1: T o phương án ban đầu:

For i:=l to m do

đổi các giá trị A[i,j] = 0 thành 1 với j ch y từ 1 ->N cho đến khi đủ số lƣợng sinh viên i muốn học tức là bằng P[i].

Bước 2:

Repeat

Tao_day_voi; // t o cột đầy, cột vơi Gán_số;

Nếu tìm đƣợc dãy vơi thì sửa;

Until không tìm đƣợc dãy vơi nữa.

Trong đ : Tao_day_voi:

Tìm trong mảng a tổng t của cột c tổng số các số 1 ít nhất.

Duyệt từ cột 1 đến cột N, nếu cột nào c tổng các số 1 = t thì cột đ đƣợc gọi là cột đầy, nếu cột nào c tổng các số 1 < t - 2 thì đ đƣợc gọi là cột vơi.

Gán số:

Xét trên từng cột:

Nếu cột j là cột đầy thì:

{

Gán số 0 cho các cột j;

Xét tất cả các hàng i, gán số j cho các hàng i chƣa đƣợc gán sô;

}

Xét trên từng hàng:

Nếu hàng i đã đƣợc gán số thì

Nếu sinh viên i c thể theo học đƣợc học phần j (coi ô [i, j] là ô trắng )

thì

Gán số i cho các cột j chƣa đƣợc gán số.

Tìm vơi: Tìm xem trong các hàng còn tồn t i cột vơi hay không. Nếu tìm đƣợc cột vơ thì sửa l i dây chuyền xen kẽ ô xanh và ô trắng, với ô xanh là các ô a[i,j] đƣợc gán giá trị bằng 1.

Ví dụ:

C 8 sinh viên đ ng k học, các sinh viên đƣợc đánh số từ 1 đến 8, nhà trường dự kiến mở lớp d y 8 học phần kí hiệu từ 1 đến 8.

Thông tin phiếu đ ng k của các sinh viên đƣợc biểu diễn trong bảng sau:

1 2 3 4 5 6 7 8

1 0 0 2 0 2 0 2 0

2 2 0 0 0 0 2 2 0

3 0 2 0 2 2 2 0 0

4 0 0 0 0 2 0 2 2

5 2 0 2 0 0 2 2 0

6 2 0 0 2 0 2 2 0

7 0 2 2 2 0 0 0 2

8 2 2 0 0 0 0 2 0

Số lƣợng học phần các sinh viên muốn theo học cho trong bảng sau:

1 2 3 4 5 6 7 8

3 4 2 4 4 3 3 4

Thực hiện ví dụ này theo thuật toán ta c kết quả nhƣ sau:

Sinh viên 1: Học các học phần: 1, 6, 8 Sinh viên 2: Học các học phần: 2, 3, 4, 5

Sinh viên 3: Học các học phần: 1, 7 Sinh viên 4: Học các học phần: 1, 2, 3, 4 Sinh viên 5: Học các học phần: 2, 4, 5, 8 Sinh viên 6: Học các học phần: 2, 3, 5 Sinh viên 7: Học các học phần: 1, 6, 7 Sinh viên 8: Học các học phần: 3, 4, 5, 6 Một số giao diện trong chương trình

Giao diện chính

Chức n ng thêm học phần cho học kỳ

Chức n ng đ ng k học phần

Chức n ng xem kết quả

Các hàm và thủ tục chính của chương trình:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace DangKyTinChi.Common {

public class Hungari {

public int[] P = null/*So Hoc Phaan sv muon hoc*/, Day = null/*Day day hay voi*/

, Gc = null/*Gan cot*/, Gh = null/*Gan hang*/;

public int[][] A = null;

public int M = 0/*So SV*/, N = 0/*So Hoc Phan*/, J0 = 0;

public void Prepare() {

this.P = new int[this.M];

this.Gc = new int[this.N];

this.Gh = new int[this.M];

this.Day = new int[this.N];

this.A = new int[M][];

for (int i = 0; i < this.M; i++) this.A[i] = new int[this.N];

for (int i = 0; i < this.M; i++)

for (int j = 0; j < this.N; j++) this.A[i][j] = 2;

}

private void Hang(int i) {

int dem = 0;

for (int j = 0; j < this.N; j++) {

if (this.A[i][j] == 0 && dem < this.P[i]) {

this.A[i][j] = 1;

dem++;

} } }

/// <summary>

/// Tao Phuong An Ban Dau /// </summary>

public void Pal() {

for (int i = 0; i < this.M; i++) {

this.Hang(i);

} }

private int TongCot(int j) {

int p = 0;

for (int i = 0; i < this.M; i++) {

if (this.A[i][j] == 1) p++;

}

return p;

}

private void TaoDayVoi() {

for (int j = 0; j < this.N; j++) this.Day[j] = 0;

int t = this.TongCot(0);

for (int j = 1; j < this.N; j++) {

int tongCotJ = this.TongCot(j);

if (t < tongCotJ) t = tongCotJ;

}

for (int j = 0; j < this.N; j++) {

int tongCotJ = this.TongCot(j);

if (t == tongCotJ) this.Day[j] = 1; //Cot Day //if (t >= tongCotJ + 2) this.Day[j] = -1; //Cot Voi 1< t -2

if (tongCotJ < t - 2) this.Day[j] = -1;

} }

private void Gan1() {

for (int j = 0; j < this.N; j++)

{

if (this.Day[j] == 1) {

this.Gc[j] = 0;

for (int i = 0; i < this.M; i++) {

if (this.A[i][j] == 1)

if (this.Gh[i] == -1) this.Gh[i] = j;

} } } }

private void Gan2() {

for (int i = 0; i < this.M; i++) {

if (this.Gh[i] > 0) {

for (int j = 0; j < this.N; j++) {

if (this.A[i][j] == 0)

if (this.Gc[j] == -1) this.Gc[j] = i;

} } } }

private void GanSo() {

int dem = 0;

for (int i = 0; i < this.M; i++) {

this.Gh[i] = -1;

for (int j = 0; j < this.N; j++) {

this.Gc[j] = -1;

dem = 0;

do {

Gan1();

Gan2();

dem++;

} while (dem == (this.N + this.M));

} }

}

private bool TimVoi() {

for (int j = 0; j < this.N; j++) {

if (this.Day[j] == -1 && this.Gc[j] > 0) {

// j 0:=j;

this.J0 = j;

return true;

break;

} }

return false;

}

private void Sua(int i, int j) {

while (i > 0 && j > 0) {

i = this.Gc[j];

this.A[i][j] = 1 - this.A[i][j];

j = this.Gh[i];

if (j > 0) this.A[i][j] = 1 - this.A[i][j];

} }

public void ThucHien() {

do {

TaoDayVoi();

GanSo();

if (TimVoi()) Sua(this.Gc[this.J0], this.J0);

} while (TimVoi());

} } }

KẾT LUẬN 1. Kết luận

Sau thời gian nghiên cứu về L thuyết đồ thị, tìm hiểu về những ứng dụng và tính thiết thực của l nh vực này, luận v n đã đ t đƣợc những kết quả nhƣ sau:

Phần l thuyết:

-Tìm hiểu các khái niệm cơ bản của đồ thị, đồ thị hai phía.

-Tìm hiểu các thuật toán giải bài toán bộ ghép cực đ i trên đồ thị hai phía và trên đồ thị tổng quát.

Phần thực nghiệm:

- Tìm hiểu được một số ứng dụng của L thuyết đồ thị và bước đầu biết cách ứng dụng l thuyết để triển khai áp dụng giải hai bài toán trong thực tế: Bài toán xếp lớp học theo tín chỉ và bài toán điều hành taxi.

-Cài đặt thử nghiệm chương trình mô phỏng thuật toán Hungari giải bài toán xếp lớp học theo học chế tín chỉ. Đây là bài toán c tính thực tế cao.

-Các thuật toán sử dụng là tìm bộ ghép cực đ i với trọng số cực tiểu trên đồ thị hai phía và thuật toán phỏng theo thuật toán Hung-ga-ri.

-Thời gian ch y bài toán nhanh.

-Giao diện thân thiện và c thể nâng cấp để áp dụng vào công việc đào t o của Trường TCKT V nh Phúc.

Bên c nh đ , luận v n còn một số nhược điểm như: Chương trình mới mô phỏng đƣợc thuật toán, chƣa mô tả và giải quyết đƣợc hết các yêu cầu phát sinh trong thực tế.

2. Hướng phát triển của đề tài:

Tiếp tục tìm hiểu về mô hình đào t o theo học chế tín chỉ để xây dựng phần mềm hoàn chỉnh, với đầy đủ chức n ng phục vụ cho công việc đào t o theo học chế tín chỉ - một mô hình đào t o còn mới và còn nhiều kh kh n.

Tìm hiểu thêm về những ứng dụng của L thuyết đồ thị để giải quyết các bài toán trong thực tế.

Một phần của tài liệu Bài toán tìm bộ ghép cực đại trên đồ thị, ứng dụng giải một số bài toán trong thực tế (Trang 69 - 80)

Tải bản đầy đủ (PDF)

(80 trang)