5. Bố cục đề tài
2.4. Bài toán lập lịch thuê thợ may hàng tháng
2.4.1. Phát biểu bài toán
Có một hợp đồng của đối tác bên Mỹ kéo dài trong t tháng, người quản lý cần phải lập lịch sử dụng thợ may mọi tháng cho dự án. Biết rằng:
Số thợ may tối thiểu cần trong tháng thứ i là stm[i].
Tiền dịch vụ khi thuê một thợ may là dV.
Tiền đền bù khi sa thải một thợ may là sT.
Lương tháng mỗi thợ may phải trả là lT.
Cần phải thuê hay sa thải bao nhiêu thợ may mỗi tháng để tổng chi phí của dự án là nhỏ nhất.
- Dòng đầu tiên lần lượt là t tháng, dV tiền dịch vụ, sT tiền sa thải và lT tiền lương.
- Dòng thứ hai là số thợ may tối thiểu phải thuê của t tháng
Dữ liệu ra: Ghi trong tệp văn bản Tailor.out gồm:
- Dòng đầu tiên là tổng chi phí nhỏ nhất của dự án. - Dòng thứ hai là số thợ may phải thuê của t tháng. Ví dụ: Tailor.inp Tailor.out 3 7 6 8 4 7 6 227 4 7 6
2.4.2. Phân tích, xử lý bài toán và lập hệ thức truy hồi
stm[i] là số thợ may cần thuê của tháng thứ i.
Smax là số thợ may của tháng cần nhiều người nhất.
Gọi c(i, j) là chi phí tối thiểu của i tháng đầu tiên nếu tại tháng thứ i có j thợ may được thuê.
Bài toán con nhỏ nhất ứng với i = 1, tháng đầu tiên: c(1, j) = j x (dV + lT) (với j = stm[1]… sMax)
c(i, j) = min {c(i - 1, k) + Chi phí để từ k thợ may thành j thợ may + Lương tháng của các nhân viên}
(với i = 2…t, j = stm[i]…smax, k = stm[i – 1]…sMax) Chi phí để từ k thợ may thành j thợ may được tính như sau:
- Nếu k < j, tức là (j – k) thợ may được thuê, thì chi phí là (k – j) x dV. - Ngược lại, tức là (k – j) thợ may bị sa thải, thì chi phí là (j – k) x sT. Kết quả bài toán là:
min {c(T, j) + Chi phí sa thải j thợ may} (với j =s[T]…sMax)
2.4.3. Thuật toán
Khởi tạo mảng hai chiều với t + 1 hàng và sMax cột.
Tính giá trị tháng thứ nhất bằng cách duyệt từ j = stm[t] đến sMax, với công thức:
c(1, j) = j x (dV + lT)
Tính giá trị các tháng từ tháng thứ 2 trở đi bằng cách duyệt từ i = 2 đến t với công thức:
c(i, j) = min {c(i - 1, k) + Chi phí để từ k thợ may thành j thợ may + Lương tháng của các nhân viên }
(với mỗi lần j = smt[i] đến sMax, tương ứng với k = smt[i – 1] đến sMax) Sau đó, tính tổng chi phí tháng thứ t với chi phí hiện tại và chi phí sau khi sa thải thợ may:
c(t + 1, j) = c(t, j) + j x sT (với j từ stm[t – 1] đến sMax)
Truy vết, sử dụng thuật toán đệ quy để tìm số thợ may được thuê của mỗi tháng.
2.4.4. Thiết kế chương trình
B1: Khởi tạo mảng hai chiều money và flag với số dòng là month + 2 và số
cột là tailorMax + 1 (số thợ may của tháng cần nhiều người nhất), mảng money dùng để lưu trữ tổng chi phí của tháng, mảng flag dùng để lưu trữ số thợ may được thuê trong tháng đó.
Khởi tạo mảng tailor với độ dài là month + 1. Giá trị các phần tử được đọc vào từ file Tailor.inp.
B2: Khởi tạo các phần tử ở dòng 1: For j từ 1 đến tailorMax
money[1][j] = j x (service + salary)
(service: tiền dịch vụ, salary: lương tháng)
B3: Khởi tạo các phần tử từ dòng 2 đến month: For i từ 2 đến month
For j từ tailor[i] đến tailorMax
money[i][j] = MAX_INT
tmp = 0
tmp = money[i – 1, k] + j x salary
If k >= j
tmp = tmp + (k – j) x release
(release: tiền sa thải)
Else
tmp = tmp + (j – k) x service
If tmp < money[i][j]
money[i][j] = tmp flag[i][j] = k
B4: Khởi tạo các phần tử ở dòng month + 1 For j từ tailor[month] đến tailorMax
money[month + 1][j] = money[month][j] + j x release
B5: Duyệt và tìm tổng tiền nhỏ nhất của hợp đồng
k = tailor[month]
totalMoney = money[month + 1][k]
For j từ k + 1 đến tailorMax
k = j
totalMoney = money[month + 1][j] Ghi totalMoney vào file Tailor.out
(k là số thợ may được thuê của tháng thứ month và totalMoney là tổng chi phí nhỏ nhất của dự án)
B6: Truy vết, đệ quy trên mảng flag để tìm ra số thợ may được thuê If i = 1
Thoát khỏi hàm
Else
Đệ quy theo phần tử (i – 1, flag[i][j]) Ghi flag[i][j] vào file Tailor.out
(flag[i][j] là số thợ may được thuê của tháng thứ i - 1)
Kết thúc. 2.4.5. Ví dụ
Ta có mảng money và flag được tính từ đề bài ví dụ ban đầu như sau: Mảng money:
Mảng flag:
Sau khi truy vết:
=> Tổng chi phí nhỏ nhất là 227 và số thợ may được thuê của các tháng lần lượt là 4, 7 và 6.