public void AutoAllocate(BackgroundWorker worker)
        {
            // just fills whatever we have :)
            int loopCount = 0;
            worker.ReportProgress(0, "Seeding...");
            foreach (Enrollment e in EnrollList)
            {
                if (e.Enrolled || e.GetRestricted() != null)
                    continue;

                Trace.WriteLine("Enroll " + e);
                e.Enrolled = true;
                worker.ReportProgress(10 * (++loopCount) / EnrollList.Count);
            }
            FullFillExcel();

            // do some magic, A* search!
            worker.ReportProgress(10, "Optimizing...");
            visited = new HashSet<string>();
            queue = new List<State>(QUEUE_LIMIT);
            best = null;

            Trace.WriteLine("Start time: " + DateTime.Now.ToLongTimeString());
            #if DEBUG
            long lastTime = DateTime.Now.Ticks;
            #endif
            CheckVisit(EnrollStatus);
            Queue(EnrollStatus);
            for (int i = 0; i < PROCESS_ROUND; i++)
            {
                State s = queue[0];
                queue.RemoveAt(0);
                Process(s);

                SortAndDrop();
                _objGen++;
                Trace.WriteLine("> i=" + i + ", B: " + best + ", H: " + queue[0] + ", W: " + queue[queue.Count - 1]);

            #if DEBUG
                long now = DateTime.Now.Ticks;
                Debug.Print("Time: " + (now - lastTime));
                lastTime = now;
            #endif
                worker.ReportProgress(10 + 90 * i / PROCESS_ROUND);
                Thread.Yield();
            }

            Trace.WriteLine("End time: " + DateTime.Now.ToLongTimeString());
            CacheClean();
            visited = null;
            queue = null;
            System.GC.Collect();
            System.GC.WaitForPendingFinalizers();

            // Final Output
            worker.ReportProgress(100, "Finishing...");
            EnrollStatus = best;
            FullFillExcel();
            best = null;
        }
 private void Process(State state)
 {
     foreach (Enrollment e in EnrollList)
     {
         EnrollStatus = state;
         if (!e.Enrolled)
         {
             Constraint[] res = e.GetRestricted();
             if (res == null)
             {
                 e.Enrolled = true;
                 if (CheckVisit(EnrollStatus)) continue;
                 Queue(EnrollStatus);
             }
             else
                 ForceEnroll(e, res, 0, null);
         }
     }
 }
        private void Queue(State state)
        {
            Debug.Assert(CheckVisit(state));

            long state_score;
            long best_score;

            if (best == null ||
                (state_score = state.GetScore()) > (best_score = best.GetScore()))
            {
                best = state;
                Trace.WriteLine("Bested by " + best.ToString());
            }
            else if (state_score == best_score)
                best = state;

            if (queue.Count < QUEUE_LIMIT ||
                state.GetScore() > queue[QUEUE_LIMIT - 1].GetScore() - QUEUE_BACK_SCORE)
                queue.Add(state);
        }
 private bool CheckVisit(State state)
 {
     return !visited.Add(state.SecurityHash);
 }