Bài toán PCCB (1 người xem)

Người dùng đang xem chủ đề này

toaninfotech

Thành viên mới
Tham gia
20/4/12
Bài viết
12
Được thích
0
Em chào anh chị
Em có một bài toán như thế này xin nhờ anh chị giải quyết giúp ạ
  1. Có một danh sách cán bộ và danh sách phòng thi
  2. Yêu cầu: Phân công cán bộ coi thi ngẫu nhiên mà không phải bốc phiếu thủ công và đưa ra kết quả vào vùng kết quả em đã tô vàng
  3. Mỗi phòng thi 2 giám thị. Mỗi giám thị chỉ coi 1 phòng thi
  4. Số lượng phòng thi có thể thay đổi theo từng buổi thi
Em xin cảm ơn anh chị trước ạ
 

File đính kèm

Không biết đúng ý chưa nửa, tôi còn e ngại nếu danh sách giám thị chỉ có 30 người còn phòng thi 16 thì tính sao.
 

File đính kèm

sao mình upload file không được.
Tại ô D2:


Mã:
=INDEX($B$2:$B$31,SMALL(IF(COUNTIF($D$1:D1,$B$2:$B$31),"",ROW(INDIRECT("1:"&ROWS($B$2:$B$31)))),RANDBETWEEN(1,31-COUNTA($D$1:D1))))
Ctrl-shift-enter

Copy xuống tới D16

Tại ô E2:
Mã:
=INDEX($B$2:$B$31,SMALL(IF(COUNTIF($D$2:$D$16,$B$2:$B$31),"",ROW(INDIRECT("1:"&ROWS($B$2:$B$31)))),RANDBETWEEN(1,15)))
Ctrl-shift-enter

E3:
Mã:
=INDEX($B$2:$B$31,SMALL(IF(COUNTIF($D$2:$D$16,$B$2:$B$31)+COUNTIF($E$2:$E2,$B$2:$B$31),"",ROW(INDIRECT("1:"&ROWS($B$2:$B$31)))),RANDBETWEEN(1,15-COUNTA($E$2:E2))))
Ctrl-shift-enter

Copy E3 xuống tờ E16
 
Không biết đúng ý chưa nửa, tôi còn e ngại nếu danh sách giám thị chỉ có 30 người còn phòng thi 16 thì tính sao.
Vâng. Đúng rồi. Vấn đề e ngại của bạn cũng là vấn đề thực tế
Mình mô tả chi tiết hơn nữa nhé
  1. Mỗi một buổi tổ chức thi sẽ có n phòng thi (được đặt tên và có danh sách đi kèm), vì thế sẽ chuẩn bị 2*n cán bộ để coi thi (Có danh sách đi kèm)
  2. Vấn đề bây giờ là làm thế nào để phân công cán bộ coi thi (một cách ngẫu nhiên để đảm bảo tính khách quan) như bên trên ạ (n là số phòng thi, mỗi buổi thi n sẽ khác nhau)
  3. Nếu đang thi mà có 1 giám thị bị ốm, thay đổi giám thị-Thay đổi dữ liệu nguồn thì kết quả phân công không đc thay đổi ngẫu nhiên nữa mà chỉ thay đổi giám thị đó mà thôi. Trong file bạn gửi thì mỗi lần thay đổi dữ liệu nguồn, kết quả phân công lại thực hiện lại 1 lần.
  4. ...
 
Lần chỉnh sửa cuối:
Vâng. Đúng rồi. Vấn đề e ngại của bạn cũng là vấn đề thực tế
Mình mô tả chi tiết hơn nữa nhé
  1. Mỗi một buổi tổ chức thi sẽ có n phòng thi (được đặt tên và có danh sách đi kèm), vì thế sẽ chuẩn bị 2*n cán bộ để coi thi (Có danh sách đi kèm)
  2. Vấn đề bây giờ là làm thế nào để phân công cán bộ coi thi (một cách ngẫu nhiên để đảm bảo tính khách quan) như bên trên ạ (n là số phòng thi, mỗi buổi thi n sẽ khác nhau)
  3. Nếu đang thi mà có 1 giám thị bị ốm, thay đổi giám thị-Thay đổi dữ liệu nguồn thì kết quả phân công không đc thay đổi ngẫu nhiên nữa mà chỉ thay đổi giám thị đó mà thôi. Trong file bạn gửi thì mỗi lần thay đổi dữ liệu nguồn, kết quả phân công lại thực hiện lại 1 lần.
  4. ...
Bạn xem lại file, để thay đổi phân công hãy click vào cái mặt thấy ghét kia, còn muốn đổi giám thị thì thay tên chổ cột B. Code trên chạy với số lượng giám thị được phân công phải lớn hơn hoặc bằng 2 lần số lượng phòng thi.
 

File đính kèm

Bạn xem lại file, để thay đổi phân công hãy click vào cái mặt thấy ghét kia, còn muốn đổi giám thị thì thay tên chổ cột B. Code trên chạy với số lượng giám thị được phân công phải lớn hơn hoặc bằng 2 lần số lượng phòng thi.
Vâng ạ. Cách giải quyết này khá hay
Nhưng Bạn ơi cho mình hỏi thêm một chút xíu nữa nhé
  1. Mỗi một buổi thi sẽ tổ chức thi riêng
  2. Sau một khoảng thời gian nào đó (cuối kỳ, cuối năm,... chẳng hạn) cần phải thống kê khối lượng coi thi của từng người
Với nhu cầu như vậy thì không biết là ta phải tổ chức dữ liệu và đưa phương án giải quyết nào hay ạ
 
Bạn xem thử có phù hợp với yêu cầu của bạn chưa.
Thật tuyệt vời. Cám ơn bạn giaiphap nhiều nhiều
Ý tưởng của bạn hay lắm. Bạn đúng là cao thủ
Vấn đề bây giờ chỉ là thời gian...Mình sẽ nghiên cứu các vấn đề phát sinh...Có gì mình sẽ post bài sau
Cám ơn bạn giaiphap
 
Lần chỉnh sửa cuối:
Bạn xem thử có phù hợp với yêu cầu của bạn chưa.
Vấn đề bây giờ đặt ra là:
  1. Nếu 1 cán bộ trong một ngày tham gia nhiều ca coi thi thì thống kê trùng ngày với cán bộ đó giải quyết tnao?
  2. Với mỗi cán bộ, cần có bảng thống kê thêm một số thông tin: Tên môn coi thi, Thời gian coi thi môn đó, Lớp nào thi ...
Mình cảm ơn trước ạ
 
Vấn đề bây giờ đặt ra là:
  1. Nếu 1 cán bộ trong một ngày tham gia nhiều ca coi thi thì thống kê trùng ngày với cán bộ đó giải quyết tnao?
  2. Với mỗi cán bộ, cần có bảng thống kê thêm một số thông tin: Tên môn coi thi, Thời gian coi thi môn đó, Lớp nào thi ...
Mình cảm ơn trước ạ
Trước hết bạn phải lập danh sách cán bộ, trong đó có các cột như ngày coi thi, môn thi, buổi coi thi... lúc đó mới tính tiếp. Lưu ý danh sách càng chi tiết, càng gọn, càng dễ thống kê thì lúc đó mới tính đến việc code két nhé.
 
file giải quyết yêu cơ bản, các yêu cầu khác tự thêm ở những dòng trên cùng
Mình mong muốn có một bản thiết kế như thế này
Không biết có ổn không. Mong nhận được sự hướng dẫn góp ý
Very Thankyou
 

File đính kèm

Trước hết bạn phải lập danh sách cán bộ, trong đó có các cột như ngày coi thi, môn thi, buổi coi thi... lúc đó mới tính tiếp. Lưu ý danh sách càng chi tiết, càng gọn, càng dễ thống kê thì lúc đó mới tính đến việc code két nhé.
Mình mong muốn có một bản thiết kế như thế này
Không biết có ổn không. Mong nhận được sự hướng dẫn góp ý
Very Thankyou
 

File đính kèm

Mình mong muốn có một bản thiết kế như thế này
Không biết có ổn không. Mong nhận được sự hướng dẫn góp ý
Very Thankyou
Mã:
Sub ThongKe()
Dim Darr(), Arr(), Ikey, Tmp, LastR As Long, S, i As Long, k As Long, j As Long
With Sheets("data")
  LastR = .Range("B" & Rows.Count).End(xlUp).Row
  If LastR < 4 Then Exit Sub
  Darr = .Range("A4:G" & LastR).Value
End With
ReDim Arr(1 To UBound(Darr) * 2, 1 To 5)
With CreateObject("scripting.dictionary")
  For i = 1 To UBound(Darr)
    If Darr(i, 1) = "" Then Darr(i, 1) = Darr(i - 1, 1)
    For j = 3 To 4
      Tmp = Darr(i, j)
      If Tmp <> "" Then
        If Not .exists(Tmp) Then
          .Add Tmp, "a" & "#" & i
        Else
          .Item(Tmp) = .Item(Tmp) & "#" & i
        End If
      End If
    Next j
  Next i
  For Each Ikey In .keys()
    k = k + 1: Arr(k, 1) = Ikey: k = k - 1
    S = Split(.Item(Ikey), "#")
    For j = 1 To UBound(S)
      k = k + 1
      Arr(k, 2) = Darr(S(j), 1)
      Arr(k, 3) = Darr(S(j), 5)
      Arr(k, 4) = Darr(S(j), 6)
      Arr(k, 5) = Darr(S(j), 7)
    Next j
  Next
End With
With Sheets("ThongKe")
  LastR = .Range("C" & Rows.Count).End(xlUp).Row
  If LastR > 4 Then .Range("B5:F" & LastR).ClearContents
  Darr = .Range("A4:G" & LastR).Value
  .Range("B5:F5").Resize(k) = Arr
End With
End Sub
Sub LuuData()
Dim Darr(), iR As Long
With Sheets("PC")
  Darr = .Range("D4:H" & .Range("D" & Rows.Count).End(xlUp).Row).Value
End With
With Sheets("data")
  iR = .Range("B" & Rows.Count).End(xlUp).Row + 1
  .Range("A" & iR) = Range("I3")
  .Range("B" & iR) = 1
  .Range("B" & iR).Resize(UBound(Darr)).DataSeries
  .Range("C" & iR).Resize(UBound(Darr), 5) = Darr
End With
End Sub
Sub DoiGiamThi()
Dim Darr(), Sarr(), Arr(), Tmp
Dim i As Integer, j As Integer, k As Integer, N As Integer
Darr = Range("B4", Range("B" & Rows.Count).End(xlUp)).Value
Arr = Range("C4:E" & Range("C" & Rows.Count).End(xlUp).Row).Value
ReDim Sarr(1 To UBound(Darr))
With CreateObject("scripting.dictionary")
  For i = 1 To UBound(Arr)
    If Arr(i, 1) <> "" Then
      For j = 2 To 3
        Tmp = Arr(i, j)
        If Tmp <> "" Then
          If Not .exists(Tmp) Then .Add Tmp, ""
        End If
      Next j
    End If
  Next i
  For i = 1 To UBound(Darr)
    Tmp = Darr(i, 1)
    If Tmp <> "" Then
      If Not .exists(Tmp) Then
        k = k + 1
        Sarr(k) = Tmp
      End If
    End If
  Next i
  If k = 0 Then MsgBox ("Khong tim thay CB co the phan cong"): Exit Sub
  N = k
  For i = 1 To UBound(Arr)
    If Arr(i, 1) <> "" Then
      For j = 2 To 3
        Tmp = Arr(i, j)
        If Arr(i, j) = "" Then
Lap:
          Tmp = Sarr(Int(Rnd() * k) + 1)
          If Not .exists(Tmp) Then
            .Add Tmp, ""
            Arr(i, j) = Tmp
            N = N - 1
            If N = 0 Then GoTo Thoat
          Else
            GoTo Lap
          End If
        End If
      Next j
    End If
  Next i
End With
Thoat:
Range("C4:E" & Range("C" & Rows.Count).End(xlUp).Row) = Arr
End Sub
Sub PhanCongGT()
Dim Rng As Range, Darr(), Sarr(), Arr(), LastR As Integer
Dim i As Integer, iR As Integer, j As Integer, k As Integer, N As Integer, M As Integer
Darr = Range("B4", Range("B" & Rows.Count).End(xlUp)).Value
LastR = Range("C" & Rows.Count).End(xlUp).Row
Set Rng = Range("C4:C" & LastR)
N = Rng.SpecialCells(xlCellTypeConstants).Count * 2
If N <= UBound(Darr) Then N = UBound(Darr)
Sarr = UniqueRandom(N)
ReDim Arr(1 To Rng.Count, 1 To 2)
For i = 1 To UBound(Arr)
  If Rng(i, 1) <> "" Then
    For j = 1 To 2
      k = k + 1
      iR = Sarr(k)
      If iR <= UBound(Darr) Then
        Arr(i, j) = Darr(iR, 1)
      Else
        Arr(i, j) = "???"
      End If
    Next j
  End If
Next i
i = Range("D" & Rows.Count).End(xlUp).Row
If i > 4 Then Range("D4:E" & i).ClearContents
Range("D4:E" & LastR) = Arr
End Sub
Function UniqueRandom(ByVal N As Long) As Variant
  Dim Arr As Variant, Darr As Variant, Tmp As Long, i As Long
  ReDim Arr(1 To N):      ReDim Darr(1 To N)
  Randomize
  For i = 1 To N
    Tmp = Int(Rnd() * N) + 1
    If Darr(Tmp) = 0 Then Darr(Tmp) = Tmp
    Arr(i) = Darr(Tmp)
    If Darr(N) = 0 Then Darr(Tmp) = N Else Darr(Tmp) = Darr(N)
    N = N - 1
  Next i
  UniqueRandom = Arr
End Function
 
Mã:
Sub ThongKe()
Dim Darr(), Arr(), Ikey, Tmp, LastR As Long, S, i As Long, k As Long, j As Long
With Sheets("data")
  LastR = .Range("B" & Rows.Count).End(xlUp).Row
  If LastR < 4 Then Exit Sub
  Darr = .Range("A4:G" & LastR).Value
End With
ReDim Arr(1 To UBound(Darr) * 2, 1 To 5)
With CreateObject("scripting.dictionary")
  For i = 1 To UBound(Darr)
    If Darr(i, 1) = "" Then Darr(i, 1) = Darr(i - 1, 1)
    For j = 3 To 4
      Tmp = Darr(i, j)
      If Tmp <> "" Then
        If Not .exists(Tmp) Then
          .Add Tmp, "a" & "#" & i
        Else
          .Item(Tmp) = .Item(Tmp) & "#" & i
        End If
      End If
    Next j
  Next i
  For Each Ikey In .keys()
    k = k + 1: Arr(k, 1) = Ikey: k = k - 1
    S = Split(.Item(Ikey), "#")
    For j = 1 To UBound(S)
      k = k + 1
      Arr(k, 2) = Darr(S(j), 1)
      Arr(k, 3) = Darr(S(j), 5)
      Arr(k, 4) = Darr(S(j), 6)
      Arr(k, 5) = Darr(S(j), 7)
    Next j
  Next
End With
With Sheets("ThongKe")
  LastR = .Range("C" & Rows.Count).End(xlUp).Row
  If LastR > 4 Then .Range("B5:F" & LastR).ClearContents
  Darr = .Range("A4:G" & LastR).Value
  .Range("B5:F5").Resize(k) = Arr
End With
End Sub
Sub LuuData()
Dim Darr(), iR As Long
With Sheets("PC")
  Darr = .Range("D4:H" & .Range("D" & Rows.Count).End(xlUp).Row).Value
End With
With Sheets("data")
  iR = .Range("B" & Rows.Count).End(xlUp).Row + 1
  .Range("A" & iR) = Range("I3")
  .Range("B" & iR) = 1
  .Range("B" & iR).Resize(UBound(Darr)).DataSeries
  .Range("C" & iR).Resize(UBound(Darr), 5) = Darr
End With
End Sub
Sub DoiGiamThi()
Dim Darr(), Sarr(), Arr(), Tmp
Dim i As Integer, j As Integer, k As Integer, N As Integer
Darr = Range("B4", Range("B" & Rows.Count).End(xlUp)).Value
Arr = Range("C4:E" & Range("C" & Rows.Count).End(xlUp).Row).Value
ReDim Sarr(1 To UBound(Darr))
With CreateObject("scripting.dictionary")
  For i = 1 To UBound(Arr)
    If Arr(i, 1) <> "" Then
      For j = 2 To 3
        Tmp = Arr(i, j)
        If Tmp <> "" Then
          If Not .exists(Tmp) Then .Add Tmp, ""
        End If
      Next j
    End If
  Next i
  For i = 1 To UBound(Darr)
    Tmp = Darr(i, 1)
    If Tmp <> "" Then
      If Not .exists(Tmp) Then
        k = k + 1
        Sarr(k) = Tmp
      End If
    End If
  Next i
  If k = 0 Then MsgBox ("Khong tim thay CB co the phan cong"): Exit Sub
  N = k
  For i = 1 To UBound(Arr)
    If Arr(i, 1) <> "" Then
      For j = 2 To 3
        Tmp = Arr(i, j)
        If Arr(i, j) = "" Then
Lap:
          Tmp = Sarr(Int(Rnd() * k) + 1)
          If Not .exists(Tmp) Then
            .Add Tmp, ""
            Arr(i, j) = Tmp
            N = N - 1
            If N = 0 Then GoTo Thoat
          Else
            GoTo Lap
          End If
        End If
      Next j
    End If
  Next i
End With
Thoat:
Range("C4:E" & Range("C" & Rows.Count).End(xlUp).Row) = Arr
End Sub
Sub PhanCongGT()
Dim Rng As Range, Darr(), Sarr(), Arr(), LastR As Integer
Dim i As Integer, iR As Integer, j As Integer, k As Integer, N As Integer, M As Integer
Darr = Range("B4", Range("B" & Rows.Count).End(xlUp)).Value
LastR = Range("C" & Rows.Count).End(xlUp).Row
Set Rng = Range("C4:C" & LastR)
N = Rng.SpecialCells(xlCellTypeConstants).Count * 2
If N <= UBound(Darr) Then N = UBound(Darr)
Sarr = UniqueRandom(N)
ReDim Arr(1 To Rng.Count, 1 To 2)
For i = 1 To UBound(Arr)
  If Rng(i, 1) <> "" Then
    For j = 1 To 2
      k = k + 1
      iR = Sarr(k)
      If iR <= UBound(Darr) Then
        Arr(i, j) = Darr(iR, 1)
      Else
        Arr(i, j) = "???"
      End If
    Next j
  End If
Next i
i = Range("D" & Rows.Count).End(xlUp).Row
If i > 4 Then Range("D4:E" & i).ClearContents
Range("D4:E" & LastR) = Arr
End Sub
Function UniqueRandom(ByVal N As Long) As Variant
  Dim Arr As Variant, Darr As Variant, Tmp As Long, i As Long
  ReDim Arr(1 To N):      ReDim Darr(1 To N)
  Randomize
  For i = 1 To N
    Tmp = Int(Rnd() * N) + 1
    If Darr(Tmp) = 0 Then Darr(Tmp) = Tmp
    Arr(i) = Darr(Tmp)
    If Darr(N) = 0 Then Darr(Tmp) = N Else Darr(Tmp) = Darr(N)
    N = N - 1
  Next i
  UniqueRandom = Arr
End Function
Trước hết xin cảm ơn bác vì những gì bác code
Nhưng khi chạy em thấy có một số vấn đề:
  1. Cùng kết quả phân công giám thị, cùng ca thi, cùng ngày tháng nhưng nhấn vào nút Lưu trữ bao nhiều lần thì nó lưu lại bấy nhiêu bản lưu
  2. Tương tự như thế, ở nút Thống kê. Khi nhấn nút Thống kế nhiều lần thì xảy ra trường hợp 1 cán bộ, coi thi 1 ca rất nhiều lần. Như vậy sẽ cho ra kết quả Thống kê ko mong muốn
 
Tôi thấy cách bổ trí dữ liệu của bạn như vậy chưa phù hợp, lý do lưu trữ thông tin như thế rất khó cho thống kê. Sheet Thống kê tôi nghĩ không cần đưa thông tin vào mà cài sẳn công thức tự động nó cập nhật vào luôn khi đưa vào danh sách lưu trữ ở sheet data. Và tạo thêm một sheet nửa để xem thông tin chi tiết quá trình coi thi của một giáo viên. Để chiều rảnh tôi thiết kế lại cái mẫu cho bạn tham khảo/
 
Trước hết xin cảm ơn bác vì những gì bác code
Nhưng khi chạy em thấy có một số vấn đề:
  1. Cùng kết quả phân công giám thị, cùng ca thi, cùng ngày tháng nhưng nhấn vào nút Lưu trữ bao nhiều lần thì nó lưu lại bấy nhiêu bản lưu
  2. Tương tự như thế, ở nút Thống kê. Khi nhấn nút Thống kế nhiều lần thì xảy ra trường hợp 1 cán bộ, coi thi 1 ca rất nhiều lần. Như vậy sẽ cho ra kết quả Thống kê ko mong muốn
2. 1 CB coi thì nhiều lần là do bạn tạo danh sách coi thi chưa tính đến phân công đồng đều, và việc chọn CB coi thi ngẫu nhiên
1. tạo thêm lệnh cảnh báo cho bạn tự quyết định có lưu hay không?
Mã:
Sub LuuData()
Dim Darr(), Sarr(), iR As Long, Ngay, Msg, Style, Title, Response
With Sheets("PC")
  Ngay = .Range("I3").Value
  If Ngay = "" Then MsgBox ("Ban phai nhap Ngay va Ca vao ô I3"): Exit Sub
  Darr = .Range("D4:H" & .Range("D" & Rows.Count).End(xlUp).Row).Value
End With
With Sheets("data")
  iR = .Range("B" & Rows.Count).End(xlUp).Row + 1
  Sarr = .Range("A4:A" & iR - 1).Value
  For i = 1 To UBound(Sarr)
    If Sarr(i, 1) = Ngay Then
      Msg = "Du lieu ngay " & Ngay & " da luu !!!" & Chr(10) & "Ban muon luu them ?"
      Style = vbYesNo + vbCritical + vbDefaultButton2
      Title = "Du lieu Ngay_Ca thi bi trung !!!"
      Response = MsgBox(Msg, Style, Title)
      If Response = vbNo Then Exit Sub Else Exit For
    End If
  Next i
  .Range("A" & iR) = Range("I3")
  .Range("B" & iR) = 1
  .Range("B" & iR).Resize(UBound(Darr)).DataSeries
  .Range("C" & iR).Resize(UBound(Darr), 5) = Darr
End With
End Sub
 
Tôi thiết kế lại mẫu bạn xem thử được không? tôi thực hiện cho excel 2013 nhé.
Vâng. Pác thiết kế và code công phu quá
Em cảm ơn bác nhiều
Em đã chạy thử và thấy mượt mà
Em đang bận ít việc ạ nên chưa test kỹ
Có gì tối em online
Thankyou very mụch
 
Tại thấy bạn chung ngành, vã lại đây cũng là cái mà mình sau này có thể sử dụng nên rảnh thiết kế coi chơi. Còn một cái mà mình chưa đủ trình độ để làm đó làm, khi phân công làm sao tránh luôn trường hợp coi thi lại phòng cũ (tức là hôm trước coi thi phòng đó rồi thì hôm sau không xếp vào phòng đó nửa), đây là trường hợp mà trường mình hay xếp, nhưng chỉ xếp tay thôi.
 
Tại thấy bạn chung ngành, vã lại đây cũng là cái mà mình sau này có thể sử dụng nên rảnh thiết kế coi chơi. Còn một cái mà mình chưa đủ trình độ để làm đó làm, khi phân công làm sao tránh luôn trường hợp coi thi lại phòng cũ (tức là hôm trước coi thi phòng đó rồi thì hôm sau không xếp vào phòng đó nửa), đây là trường hợp mà trường mình hay xếp, nhưng chỉ xếp tay thôi.

con người xếp được thì máy cũng xếp được :D:D
 
Bạn biết chỉ mình một giải thuật xếp không bị trùng được không?
Theo em nghĩ, nếu cán bộ có thêm Mã cán bộ thì thuật toán xếp coi thi không bị trùng coi như đã giải quyết được
Các bác cứ nghiên cứu đi ạ. Bác nào có phương án hay thì chỉ cho em tham khảo với
Thanks
 
Theo em nghĩ, nếu cán bộ có thêm Mã cán bộ thì thuật toán xếp coi thi không bị trùng coi như đã giải quyết được
Các bác cứ nghiên cứu đi ạ. Bác nào có phương án hay thì chỉ cho em tham khảo với
Thanks
Hình như bạn bị nhầm thì phải, ở bài trước thì nó đã xếp không bị trùng rồi mà. Cái nan giải ở đây là xếp lịch cho các ngày coi thi của giáo viên sao cho không coi thi trùng trở lại phòng thi. Vd hôm nay GV A coi thi phòng 1 rồi, sang ngày hôm sau xếp lịch phải bỏ phòng 1 đó ra khi xếp cho GV A này.
 
xếp lịch cho các ngày coi thi của giáo viên sao cho không coi thi trùng trở lại phòng thi. Vd hôm nay GV A coi thi phòng 1 rồi, sang ngày hôm sau xếp lịch phải bỏ phòng 1 đó ra khi xếp cho GV A này.
- Lập ra cái điều kiện (1).
- Đưa dữ liệu vào đã xếp vào một bảng nhớ (2)
- Xếp lần tiếp theo thì đối chiếu (2) theo (1).
 
Hôm nay khuya quá, để mai mình lập dữ liệu giả lập bạn giúp mình phần giải thuật nhé.
để đơn giản bạn có thể làm theo trình tự:
-xét lấy dữ liệu của lần phân công trước hoặc của ca trước đó ngày hôm nay hoặc ngày trước đó tùy bạn sau đó gán điều kiện xét không trùng: Phòng &"#"& tên GT vào Dic
-chạy vòng lập

TroLai:
code tạo danh sách phân công
For ...chạy từng giám thị
xét Phòng &"#"& tên GT tồn tại trong Dic thì Goto TroLai
next
lấy kết quả
 
Đây là file mẫu bác nào giúp hộ mình.
 

File đính kèm

con người xếp được thì máy cũng xếp được :D:D

Trên nguyên tắc thì vậy. Trên thực tế thì cái khó nó nằm giữa chỗ chuyển cái logic "con người làm" sang cho máy nó hiểu. Hầu hết các trường hợp là do ngừoi ta làm theo phản xạ, đến chừng bảo ghi lại quy trình thì đớ cả ra.
Trước mắt là những bài hỏi ở đây, giữa người và người còn lô gic loạn xạ hết lên. Một bài hỏi phải "không đúng/chưa đúng/thêm chút nữa" cả chục lần mới xong.

Bởi vậy trong tin học có cái gọi là bảng chân lý (truth table) để ngừoi làm việc ghi lại các trường hợp IF's của vấn đề.

Chú: đối với vấn đề sắp xếp phân công, nghành toán áp dụng có môn Nghiên Cứu Vận Hành (Operations Research), ngành này có những cong thức và giải thuật để tối ưu các cách sắp xếp. Rất tiếc là tôi khong chuyên về môn toán này. Nếu các bạn muốn nghiên cứu thì nên vào các diễn đàn toán áp dụng mà hỏi. Tuy nhiên cũng cần khuyến cáo là ba cái này có thể kèm theo hàm thư viện hàng trăm functions.
 
Đây là file mẫu bác nào giúp hộ mình.
bạn kiểm tra lại code
Mã:
Option Explicit
Sub PhanCongGT()
Dim Dic As Object, Darr(), PTarr(), Rnd_N(), Sarr(), Rnd_Ca(), Arr(), DStruoc As Variant
Dim j As Integer, i As Integer, k As Integer, iR As Integer, N As Long, Gt As String
Set Dic = CreateObject("Scripting.Dictionary")
With Sheets("DS")
  Darr = .Range("B4:J" & .Range("B" & .Rows.Count).End(xlUp).Row).Value
  PTarr = .Range("M5:M" & .Range("M" & .Rows.Count).End(xlUp).Row).Value
End With
N = UBound(PTarr) * 2
ReDim Arr(1 To UBound(Darr) - 1, 1 To UBound(Darr, 2) - 1)
For j = 2 To UBound(Darr, 2)
  Sarr = DSgiamthi(Darr, j, N)
  If Sarr(N) = "vuot" Then
    MsgBox "so nguoi chon ngay " & Darr(1, j) & " nhieu hon yeu cau", vbInformation
    Exit Sub
  End If
  If Sarr(N) = "thieu" Then
    MsgBox "so nguoi chon ngay " & Darr(1, j) & " it hon yeu cau", vbInformation
    Exit Sub
  End If
  If j > 2 Then
    Dic.RemoveAll
    For k = 1 To N
      Dic.Add DStruoc(k), ""
    Next k
  End If
  Rnd_Ca = UniqueRandomNum(1, N, N / 2)
Lap:
  ReDim DStruoc(1 To N)
  Rnd_N = UniqueRandomNum(1, N, N)
    For k = 1 To N
      iR = ((Rnd_N(k, 1) - 1) \ 2) + 1
      Gt = "-GT2"
      For i = 1 To N / 2
        If k = Rnd_Ca(i, 1) Then Gt = "-GT1": Exit For
      Next i
      Arr(Sarr(k), j - 1) = PTarr(iR, 1) & Gt
      DStruoc(k) = Sarr(k) & "#" & PTarr(iR, 1)
      If Dic.exists(DStruoc(k)) Then GoTo Lap
    Next k
Next j
With Sheets("PC")
  .Range("C5:J" & .Range("A" & Rows.Count).End(xlUp).Row).ClearContents
  .Range("C5").Resize(UBound(Darr) - 1, UBound(Arr, 2)) = Arr
End With
MsgBox "Da phan cong coi thi xong, qua sheet PC de xem danh sach phan cong", vbInformation
End Sub
Function DSgiamthi(ByVal Darr As Variant, ByVal Col As Long, ByVal N As Long) As Variant
  Dim Arr(), i As Integer, k As Long
  ReDim Arr(1 To N)
  For i = 2 To UBound(Darr)
    If UCase(Darr(i, Col)) = "X" Then
      k = k + 1
      If k > N Then
        Arr(N) = "vuot"
        DSgiamthi = Arr
        Exit Function
      End If
      Arr(k) = i - 1
    End If
  Next i
  If Arr(N) = "" Then Arr(N) = "thieu"
  DSgiamthi = Arr
End Function
Function UniqueRandomNum(Bottom As Long, Top As Long, Amount As Long)
  'Application.Volatile '<--- Neu muon gia tri thay doi khi bam F9
  On Error Resume Next
  If Amount > Top - Bottom + 1 Then Amount = Top - Bottom + 1
  With CreateObject("Scripting.Dictionary")
    Do
      .Add Int(Rnd() * (Top - Bottom + 1)) + Bottom, ""
    Loop Until .Count = Amount
    UniqueRandomNum = WorksheetFunction.Transpose(.Keys)
  End With
End Function
 
bạn kiểm tra lại code
Mã:
Option Explicit
Sub PhanCongGT()
Dim Dic As Object, Darr(), PTarr(), Rnd_N(), Sarr(), Rnd_Ca(), Arr(), DStruoc As Variant
Dim j As Integer, i As Integer, k As Integer, iR As Integer, N As Long, Gt As String
Set Dic = CreateObject("Scripting.Dictionary")
With Sheets("DS")
  Darr = .Range("B4:J" & .Range("B" & .Rows.Count).End(xlUp).Row).Value
  PTarr = .Range("M5:M" & .Range("M" & .Rows.Count).End(xlUp).Row).Value
End With
N = UBound(PTarr) * 2
ReDim Arr(1 To UBound(Darr) - 1, 1 To UBound(Darr, 2) - 1)
For j = 2 To UBound(Darr, 2)
  Sarr = DSgiamthi(Darr, j, N)
  If Sarr(N) = "vuot" Then
    MsgBox "so nguoi chon ngay " & Darr(1, j) & " nhieu hon yeu cau", vbInformation
    Exit Sub
  End If
  If Sarr(N) = "thieu" Then
    MsgBox "so nguoi chon ngay " & Darr(1, j) & " it hon yeu cau", vbInformation
    Exit Sub
  End If
  If j > 2 Then
    Dic.RemoveAll
    For k = 1 To N
      Dic.Add DStruoc(k), ""
    Next k
  End If
  Rnd_Ca = UniqueRandomNum(1, N, N / 2)
Lap:
  ReDim DStruoc(1 To N)
  Rnd_N = UniqueRandomNum(1, N, N)
    For k = 1 To N
      iR = ((Rnd_N(k, 1) - 1) \ 2) + 1
      Gt = "-GT2"
      For i = 1 To N / 2
        If k = Rnd_Ca(i, 1) Then Gt = "-GT1": Exit For
      Next i
      Arr(Sarr(k), j - 1) = PTarr(iR, 1) & Gt
      DStruoc(k) = Sarr(k) & "#" & PTarr(iR, 1)
      If Dic.exists(DStruoc(k)) Then GoTo Lap
    Next k
Next j
With Sheets("PC")
  .Range("C5:J" & .Range("A" & Rows.Count).End(xlUp).Row).ClearContents
  .Range("C5").Resize(UBound(Darr) - 1, UBound(Arr, 2)) = Arr
End With
MsgBox "Da phan cong coi thi xong, qua sheet PC de xem danh sach phan cong", vbInformation
End Sub
Function DSgiamthi(ByVal Darr As Variant, ByVal Col As Long, ByVal N As Long) As Variant
  Dim Arr(), i As Integer, k As Long
  ReDim Arr(1 To N)
  For i = 2 To UBound(Darr)
    If UCase(Darr(i, Col)) = "X" Then
      k = k + 1
      If k > N Then
        Arr(N) = "vuot"
        DSgiamthi = Arr
        Exit Function
      End If
      Arr(k) = i - 1
    End If
  Next i
  If Arr(N) = "" Then Arr(N) = "thieu"
  DSgiamthi = Arr
End Function
Function UniqueRandomNum(Bottom As Long, Top As Long, Amount As Long)
  'Application.Volatile '<--- Neu muon gia tri thay doi khi bam F9
  On Error Resume Next
  If Amount > Top - Bottom + 1 Then Amount = Top - Bottom + 1
  With CreateObject("Scripting.Dictionary")
    Do
      .Add Int(Rnd() * (Top - Bottom + 1)) + Bottom, ""
    Loop Until .Count = Amount
    UniqueRandomNum = WorksheetFunction.Transpose(.Keys)
  End With
End Function
Code chạy ngon nhưng còn một chổ bác giúp tiếp luôn chứ tôi nhìn code rối quá. Còn trường hợp là hôm nay phân công giáo viên A coi phòng 6 và làm giám thị 1, nhưng sang ngày khác lại phân công lại chính giáo viên A này cũng phong 6 nửa chỉ có khác là giám thị 2. Ý tôi muốn là không được phân công giáo viên A này coi thi lại phòng 6 nửa, dù là giám thị 1 hay giám thị 2. Cụ thể hình phía dưới, sau khi chạy code phân công thì giáo viên Lý Thiên Bảo lại xếp lịch coi thi trùng phòng số 6.
Hinh.jpg
 
Code chạy ngon nhưng còn một chổ bác giúp tiếp luôn chứ tôi nhìn code rối quá. Còn trường hợp là hôm nay phân công giáo viên A coi phòng 6 và làm giám thị 1, nhưng sang ngày khác lại phân công lại chính giáo viên A này cũng phong 6 nửa chỉ có khác là giám thị 2. Ý tôi muốn là không được phân công giáo viên A này coi thi lại phòng 6 nửa, dù là giám thị 1 hay giám thị 2. Cụ thể hình phía dưới, sau khi chạy code phân công thì giáo viên Lý Thiên Bảo lại xếp lịch coi thi trùng phòng số 6.
View attachment 175512
code viết chạy 1 lần tất cả các ngày thì không trùng, bạn kiểm tra file
nếu chạy nhiều lần thì phải viết lại
 

File đính kèm

code viết chạy 1 lần tất cả các ngày thì không trùng, bạn kiểm tra file
nếu chạy nhiều lần thì phải viết lại
Vẫn còn bị trùng bạn ơi, tôi có ý kiến thế này khi chọn giáo viên xếp vào phòng thì đưa cả GT1 và GT2 vào trong Dic (Dic.Add) luôn (mặc dù chỉ chọn là GT1 hay GT2) vậy lần sau kiểm tra Dic.exists(DStruoc(k)) thì nó phát hiện ngay. Sẳn bạn sửa luôn chổ này, có thể chọn số lượng giáo viên coi thi nhiều hơn thực tế (ngừa trường hợp gv vắng thì còn người thay thế), tức là giả sử có 10 phòng thi thì có thể chọn hơn 20 (22, 23 ...) giáo viên coi thi (đánh dấu X nhiều hơn 20 giáo viên) trong ngày đó, cứ phân công bất kỳ vì có giáo viên dư thì không coi thi ngày đó cũng được (phục vụ hội đồng thi).
 
Vẫn còn bị trùng bạn ơi, tôi có ý kiến thế này khi chọn giáo viên xếp vào phòng thì đưa cả GT1 và GT2 vào trong Dic (Dic.Add) luôn (mặc dù chỉ chọn là GT1 hay GT2) vậy lần sau kiểm tra Dic.exists(DStruoc(k)) thì nó phát hiện ngay. Sẳn bạn sửa luôn chổ này, có thể chọn số lượng giáo viên coi thi nhiều hơn thực tế (ngừa trường hợp gv vắng thì còn người thay thế), tức là giả sử có 10 phòng thi thì có thể chọn hơn 20 (22, 23 ...) giáo viên coi thi (đánh dấu X nhiều hơn 20 giáo viên) trong ngày đó, cứ phân công bất kỳ vì có giáo viên dư thì không coi thi ngày đó cũng được (phục vụ hội đồng thi).
mình không đọc kỹ yêu cầu trong file nên hiểu nhầm, bạn kiểm tra lại file
trong code mình có ghi chú, mình không quen cách ghi chú và đặt tên biến có gì bạn chỉnh lại
với số GV nhiều và số buổi của 1 GV ít, code dể hoàn thành, nếu ngược lại thì phải chạy nhiều lần
code không quan tâm đến Tên giáo viên và ngày, chỉ xử lý hoàn toàn trên thứ tự dòng và cột
 

File đính kèm

mình không đọc kỹ yêu cầu trong file nên hiểu nhầm, bạn kiểm tra lại file
trong code mình có ghi chú, mình không quen cách ghi chú và đặt tên biến có gì bạn chỉnh lại
với số GV nhiều và số buổi của 1 GV ít, code dể hoàn thành, nếu ngược lại thì phải chạy nhiều lần
code không quan tâm đến Tên giáo viên và ngày, chỉ xử lý hoàn toàn trên thứ tự dòng và cột
Cảm ơn bạn, code chạy ngon rồi.
 
Cảm ơn bạn, code chạy ngon rồi.
vẩn còn sót, bạn chỉnh lại code
Mã:
Sub PhanCongGT()
Dim Dic As Object, Darr(), PTarr(), Rnd_M(), Sarr(), Rnd_gt12(), Arr(), DStruoc As Variant
Dim j As Integer, i As Integer, k As Integer, iR As Integer, N As Long, M As Long, S As Long, GT1_2 As String, PT As String
Set Dic = CreateObject("Scripting.Dictionary")
With Sheets("DS")
  Darr = .Range("B4:J" & .Range("B" & .Rows.Count).End(xlUp).Row).Value
  PTarr = .Range("M5:M" & .Range("M" & .Rows.Count).End(xlUp).Row).Value
End With
N = UBound(PTarr) * 2
ReDim Arr(1 To UBound(Darr) - 1, 1 To UBound(Darr, 2) - 1)
For j = 2 To UBound(Darr, 2)
  Sarr = DSgiamthi(Darr, j, N) ' Danh sach so thu tu cua giam thi và du phong
  M = UBound(Sarr) ' so giam thi và du phòng
  If M < N Then
    MsgBox "so nguoi chon ngay " & Darr(1, j) & " it hon yeu cau", vbInformation
    Exit Sub
  End If
  If j > 2 Then ' gan gia tri loai trung
    For k = 1 To UBound(DStruoc)
      Dic.Item(DStruoc(k)) = ""
    Next k
  End If
  Rnd_gt12 = UniqueRandomNum(1, N, N / 2) ' chon giam thi 1, 2 ngau nhien
Lap:
  S = S + 1
  If S = 50000 Then 'So vòng lap cho phep de chu dong End Sub, có the tang len
    MsgBox "Chua xep duoc, Phai chay xep lich lai", vbInformation
    Exit Sub
  End If
  ReDim DStruoc(1 To M) 'DS gán Dic de loai trùng
  Rnd_M = UniqueRandomNum(1, M, M) ' chon phong thi ngau nhien
    For k = 1 To M
      iR = ((Rnd_M(k, 1) - 1) \ 2) + 1
      If iR <= N / 2 Then ' xep giam thi
        PT = PTarr(iR, 1)
        GT1_2 = "-GT2"
        For i = 1 To N / 2
          If k = Rnd_gt12(i, 1) Then GT1_2 = "-GT1": Exit For
        Next i
      Else 'xep du phong
        GT1_2 = "":  PT = "Du Tru"
      End If
      Arr(Sarr(k), j - 1) = PT & GT1_2
      DStruoc(k) = Sarr(k) & "#" & PT
      If Dic.exists(DStruoc(k)) Then GoTo Lap
    Next k
Next j
With Sheets("PC")
  .Range("C5:J" & .Range("A" & Rows.Count).End(xlUp).Row).ClearContents
  .Range("C5").Resize(UBound(Darr) - 1, UBound(Arr, 2)) = Arr
End With
MsgBox "Da phan cong coi thi xong, qua sheet PC de xem danh sach phan cong", vbInformation
End Sub

Function DSgiamthi(ByVal Darr As Variant, ByVal Col As Long, ByVal N As Long) As Variant
  Dim Arr(), i As Integer, k As Long
  For i = 2 To UBound(Darr)
    If UCase(Darr(i, Col)) = "X" Then
      k = k + 1
      ReDim Preserve Arr(1 To k)
      Arr(k) = i - 1
    End If
  Next i
  DSgiamthi = Arr
End Function
 
Những bài dạng này phải dùng phương pháp vét cạn chứ làm kiểu ăn may thì khi tỷ lệ số trường hợp thỏa điều kiện thấp thì có chạy đến tết cũng không ra.
 
Những bài dạng này phải dùng phương pháp vét cạn chứ làm kiểu ăn may thì khi tỷ lệ số trường hợp thỏa điều kiện thấp thì có chạy đến tết cũng không ra.
Đúng là cách này sẽ gặp rắc rối nếu có điều kiện thỏa mãn thấp, nhưng do trình độ để viết thuật toán vét cạn của mình để giải quyết bài này thì hơi bị khó, nếu bạn có thuật toán hay chia sẻ để mình học hỏi thì cảm ơn bạn nhiều!
 
Thông thường người ta dùng phương pháp đệ quy để thực hiện thuật toán vét cạn nhưng hôm trước có trường hơp code đệ quy chạy bị lỗi (máy bị máy không) nên ở bài này tôi không dùng đệ quy.

Code trong file đính kèm chưa chọn ngẫu nhiên. Vấn đề này không khó, tôi để dành cho bạn.

Code này có một điểm hạn chế.
 

File đính kèm

Thông thường người ta dùng phương pháp đệ quy để thực hiện thuật toán vét cạn nhưng hôm trước có trường hơp code đệ quy chạy bị lỗi (máy bị máy không) nên ở bài này tôi không dùng đệ quy.

Code trong file đính kèm chưa chọn ngẫu nhiên. Vấn đề này không khó, tôi để dành cho bạn.

Code này có một điểm hạn chế.
Ok, cảm ơn bạn, để tôi về nghiên cứu thêm phần ngẫu nhiên.
 
Thông thường người ta dùng phương pháp đệ quy để thực hiện thuật toán vét cạn nhưng hôm trước có trường hơp code đệ quy chạy bị lỗi (máy bị máy không) nên ở bài này tôi không dùng đệ quy.

Code trong file đính kèm chưa chọn ngẫu nhiên. Vấn đề này không khó, tôi để dành cho bạn.

Code này có một điểm hạn chế.
Thông thường người ta dùng phương pháp đệ quy để thực hiện thuật toán vét cạn nhưng hôm trước có trường hơp code đệ quy chạy bị lỗi (máy bị máy không) nên ở bài này tôi không dùng đệ quy.

Code trong file đính kèm chưa chọn ngẫu nhiên. Vấn đề này không khó, tôi để dành cho bạn.

Code này có một điểm hạn chế.
Code này có một điểm hạn chế? chọn dư một người nó chạy không mỏi mệt
 
Code này có một điểm hạn chế? chọn dư một người nó chạy không mỏi mệt
Đó không phải là vấn để tôi đề cập.
Dữ liệu không hợp lệ là do lỗi của người dùng. Cái gì cũng phải có nguyên tắc, người viết code không thể (và cũng không nên) lường hết tất cả các trường hợp ngoài quy luật để xử lý.
 
Đó không phải là vấn để tôi đề cập.
Dữ liệu không hợp lệ là do lỗi của người dùng. Cái gì cũng phải có nguyên tắc, người viết code không thể (và cũng không nên) lường hết tất cả các trường hợp ngoài quy luật để xử lý.
đúng là viết code khó thật, viết cho người khác dùng càng khó hơn, phải qui định người dùng được làm gì và không được làm gì, nhiều lúc đáng ra chỉ vài dòng lệnh nếu người dùng hiểu biết và cẩn thận, lại phải viết lòng vòng rỏ khổ
 
đúng là viết code khó thật, viết cho người khác dùng càng khó hơn, phải qui định người dùng được làm gì và không được làm gì, nhiều lúc đáng ra chỉ vài dòng lệnh nếu người dùng hiểu biết và cẩn thận, lại phải viết lòng vòng rỏ khổ
Bạn trích dẫn bài của tôi có phải là đang nói với tôi hoặc nói về tôi? Nếu đúng thì vui lòng nói rõ ràng. Đừng bóng gió vu vơ không có cơ sở.
 
Bạn trích dẫn bài của tôi có phải là đang nói với tôi hoặc nói về tôi? Nếu đúng thì vui lòng nói rõ ràng. Đừng bóng gió vu vơ không có cơ sở.
đang trao đổi với bạn về khó khăn thực tế khi viết code trên diễn đàn, nhiều khi dữ liệu không đầy đủ, trình bày ý tưởng mơ hồ, lúc thêm lúc bớt, người dùng nhập lung tung, phải đoán mò và viết kèm theo câu hên xui
 
Những bài dạng này phải dùng phương pháp vét cạn chứ làm kiểu ăn may thì khi tỷ lệ số trường hợp thỏa điều kiện thấp thì có chạy đến tết cũng không ra.

không hẳn vậy. Ai nấy có "võ công" riêng của mình. Bạn không nên nói người khác phải dùng cái nào mới hợp lý.
Với bài này thì tỉ lệ số trường hợp thỏa điều kiện không ít đâu, kể cả là khi cần xếp 22 GT vào 11 phòng thi cho 11 ngày.
Nếu chọn giải thuật tìm ngẫu nhiên thì chìa khóa ở cách vận dụng hàm RND() nghệ thuật tới đâu thôi.
Ở đây không phải chỉ mỗi bạn giaiphap xem đề tài này, nếu có thể mong bạn giải đáp luôn cách nào để sử dụng code của bạn tạo ra ngẫu nhiên kết quả phân chia.
Thay mặt cộng đồng cám ơn bạn.
Tôi cũng trình bày 1 cách sử dụng hàm RND() để làm bài này. Rất vui được giao lưu với các bạn.

Mã:
Public Sub hello()
Dim arr, r As Long, c As Long, k As Long, conLaiArr, rndNum As Long, dsPhong
Dim danhDauPhong() As Boolean, danhDauGT() As Boolean, tmp_danhDauGT() As Long
Dim soLuongDaChon As Long, soLuongGT As Long, vitriGT As Long
arr = Sheet1.Range("C5:J49").Value
'arr = Sheet4.Range("A5:K26").Value
dsPhong = Sheet1.Range("M5:M15").Value
soLuongGT = 2 * UBound(dsPhong)

'lap. bang? danh' dau' danh sach' cac' phong` thi da~ gac' cua? tung` giam' thi.
'chieu` doc. la` giam' thi.
'chieu` ngang la` cac' vi. tri' cua? phong` thi
'trang. thai' mac. dinh. = false
'khi GT da~ gac' phong` thi X , ta danh' dau' lai. vi. tri' = true
'va` danh' dau' kem` them vi. tri' GT2 cung phong` X vao` bang? = true
ReDim danhDauGT(1 To UBound(arr), 1 To soLuongGT)
Randomize
For c = 1 To UBound(arr, 2) Step 1
retry:
    'trong moi~ ngay` thi, lap. 1 bang? danh' dau' phong` thi
    'vi. tri' da~ chon. duoc. danh' dau' lai. = true
    ReDim danhDauPhong(1 To soLuongGT)
    ReDim tmp_danhDauGT(1 To UBound(arr))
    soLuongDaChon = 0
    For r = 1 To UBound(arr) Step 1
        If arr(r, c) <> "" Then
            conLaiArr = tinhGTconLai(danhDauPhong, danhDauGT, r)
            If Not IsEmpty(conLaiArr) Then
                rndNum = conLaiArr(Int(UBound(conLaiArr) * Rnd) + 1)
                danhDauPhong(rndNum) = True
                'luu tru~ tam. thoi` cac vi. tri da chon.
                tmp_danhDauGT(r) = rndNum
               
                'khi so luong GT  da duoc chon. day` du? , ket thuc vong lap. ne' bug
                'Thi du. phan chia 11 GT cho 5 phong` thi` co 1 GT duoc. ngoi` choi
                soLuongDaChon = soLuongDaChon + 1
                If soLuongDaChon = soLuongGT Then Exit For
            Else
                GoTo retry
            End If
        End If
    Next
   
    'qua' trinh` lua chon. GT trong 1 ngay` thanh` cong, cap. nhat. vao` arr va danhDauGT
    For r = 1 To UBound(tmp_danhDauGT) Step 1
        vitriGT = tmp_danhDauGT(r)
        If vitriGT > 0 Then
            k = WorksheetFunction.RoundUp(vitriGT / 2, 0)
            'cap. nhat. cac' danh' dau' tam. thoi` vao` danhDauGT
            danhDauGT(r, vitriGT) = True
            'tinh' luon vi. tri GT2 con` lai. cua? 1 phong` vao` danh sach da~ gac' thi cua? GT do'
            If vitriGT Mod 2 = 0 Then
                danhDauGT(r, vitriGT - 1) = True
                'cap. nhat. GT da chon. vao` arr ket' qua?
                arr(r, c) = dsPhong(k, 1) & "_GT2"
            Else
                danhDauGT(r, vitriGT + 1) = True
                arr(r, c) = dsPhong(k, 1) & "_GT1"
            End If
        End If
    Next
   
    'neu So Ngay` thi vuot qua so luong Phong` thi, Reset danhDauGT tinh' lai. tu` dau`
    'vi` luc' nay` khong the bao? dam? luat. choi ban dau`
    If c = UBound(dsPhong) Then ReDim danhDauGT(1 To UBound(arr), 1 To soLuongGT)
Next
Sheet2.Range("C5").Resize(UBound(arr), UBound(arr, 2)).Value = arr
'Sheet4.Range("M5").Resize(UBound(arr), UBound(arr, 2)).Value = arr
End Sub

Private Function tinhGTconLai(danhDauPhong() As Boolean, danhDauGT() As Boolean, cRow As Long) As Variant
Dim readyArr, r As Long, k As Long
For r = 1 To UBound(danhDauPhong) Step 1
    If Not danhDauPhong(r) Then
        If Not danhDauGT(cRow, r) Then
            k = k + 1
            If IsEmpty(readyArr) Then ReDim readyArr(1 To 1) Else ReDim Preserve readyArr(1 To k)
            readyArr(k) = r
        End If
    End If
Next
tinhGTconLai = readyArr
End Function
 

File đính kèm

Với code của tôi, nếu muốn có kết quả ngẫu nhiên tôi sẽ xáo trộn ngẫu nhiên dữ liệu đầu vào.
 

Bài viết mới nhất

Back
Top Bottom