Solving the assignment problem

Assignment problem is a typical backtracking problem, the solution can be very accurate idea of ​​using the issue to get back. We do a systematic analysis of a case for the following:

Problem Description

There \ (n \) jobs to be assigned to \ (n \) individual to complete, each person completed one. The first \ (I \) Personal completion of the \ (K \) parts work time used is a positive integer \ (T_ {IK} \) , where \ (. 1 \ Leq I, K \ n-Leq \) . Determine an allocation scheme, so that it is completed \ (n-\) parts of the sum of the minimum working time.

Input contains \ (n + 1 \) line.

The first acts of a positive integer \ (the n-\) .

2 to the second line \ (n + 1 \) rows each row contains \ (n-\) positive integers, forming a \ (n \ times n \) matrix. In this matrix, the \ (I \) row \ (K \) column element \ (t_ {ik} \) represents the \ (I \) Personal completion of the \ (K \) element work to use time.

An output line, comprising a positive integer representing the total time of all minimum allocation scheme.

Limits:

\ (1 \ leq n \ leq 15 \)

\ (1 \ leq t_ {i} \ leq 10 ^ 4 \)

Sample input:

5
9 2 9 1 9
1 9 8 9 6
9 9 9 9 1
8 8 1 8 4
9 1 7 8 9

Sample output:

5

problem analysis

Since each person must be assigned to work, where you can build a two-dimensional array time[i][j]to represent \ (i \) individuals completed \ (j \) time spent on the job number. Given a cycle, distribution of work from one person to start the cycle until all assigned to. For the first \ (i \) individual allocation of work, recycling check whether each work has been allocated, not allocated to \ (i \) personal, or check the next job. A one-dimensional array can be used is_working[j]to represent the first \ (j \) is working number has been assigned, unassigned it is_working[j]=0, otherwise is_working[j]=1. Use back thought, at the end of the workers on a loop back to the workers, to cancel the allocation of work, and go to work until the next allocation can be allocated so far. In this way, it has been traced back to the first one after the workers will be able to get all the feasible solutions. In the assignment checking, in fact, determined to obtain a first dimension of the two-dimensional array index when a feasible solution and second dimensions varies index varies. And we do this is to get \ (\ n-) the sum of the minimum time of a job, and the solution can row a minimum, so the need to define a global variable cost_time_total_minrepresents the final sum of the time, the initial cost_time_total_minof time[i][i]the sum, i.e., a diagonal and the sum of working hours. When everyone finished assigning work, comparing \ (count \) and cost_time_total_minthe size, if \ (count \) is less than cost_time_total_min, prove to find an optimal solution in the back, then put the \ (count \) assigned tocost_time_total_min. However, considering the complexity of the algorithm, there's a pruning optimization of the work can be done. Is calculated in the local cost of each variable \ (count \) value, and if it is judged \ (count \) has been greater than cost_time_total_min, no need to allocate further down, because then the resulting solution is not necessarily the optimal solution.

Implementation code

#include <cstdio>
#define N 16
int is_working[N] = {0};// 某项工作是否被分配
int time[N][N];// 完成某项工作所需的时间
int cost_time_total_min;// 完成 n 份工作的最小时间总和
// i 表示第几个人,count 表示工作费用总和
inline void work(int i, int count, int n){
    // 如果 i 超出了所能分配的最大工作件数,表示分配完成,并且 count 比原来 cost_time_total_min 花费少 则更新 cost_time_total_min 的值
    if(i > n && count < cost_time_total_min){
        cost_time_total_min = count;
        return;
    }
    // 回溯思想 
    if(count < cost_time_total_min){
        // j 表示第几件工作
        for(int j = 1 ; j <= n; j++){
            // 如果工作未被分配 is_working = 0
            if(is_working[j] == 0){
                // 分配工作 is_working = 1
                is_working[j] = 1;
                //工作交给第 i + 1 个人
                work(i + 1, count + time[i][j], n);
                //在一轮迭代完成之后,返回到上一个人,要对此次的工作进行重新分配,将 is_working[j] 重设为 0
                is_working[j] = 0;
            }
        }
    }
}
int main(int argc, char const *argv[])
{
    setvbuf(stdin, new char[1 << 20], _IOFBF, 1 << 20);
    setvbuf(stdout, new char[1 << 20], _IOFBF, 1 << 20);
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            scanf("%d", &time[i][j]);
        }
        cost_time_total_min += time[i][i];
    }
    work(1, 0, n);
    printf("%d\n", cost_time_total_min);
    return 0;
}

Guess you like

Origin www.cnblogs.com/ECJTUACM-873284962/p/11622324.html