Finding the minimum value

六月ゝ 毕业季﹏ 提交于 2021-02-08 09:09:12

问题


I can't begin to understand how to approach this problem. Can someone help me to just point me in the direction as to how I can approach it?

N tasks are given and there are M workers that are available. Each worker can takes different times to complete each task. The time taken by each worker for every task is given. At any time only one task can be worked on by only one worker. But the condition is once a worker has stopped working, he can't work on any task again. I want to find out what is the minimum time required to finish all the tasks. Here's an example-

M = 3
N = 4 {T1, T2,T3,T4}
No of days required by each worker (Wi) for each task (Ti) -

There are many ways to finish the task, some of them are -

  1. All the tasks are done by the W1 ===> total time taken = 1+2+2+3 = 8
  2. All the tasks are done by the W2 ===> total time taken = 3+1+3+2 = 9
  3. All the tasks are done by the W3 ===> total time taken = 1+1+6+6 = 14
  4. T1,T2,T3 done by W1 and T4 done by W2 ===> total time taken = 1+2+2+2 = 7
  5. T1,T2 done by W1 and T3,T4 done by W3 ===> total time taken = 1+2+6+6 = 15
  6. T1,T2 done by W3, T3 done by W1 and T4 done by W2 ===> total time taken = 1+1+2+2 = 6

There are more possible ways but the one that gives the smallest time taken is the 6th one (also shown in the picture below).

I was just able to understand how to do it when the number of workers are only 2. I did it this way -

#include<iostream>
using namespace std;

int N=4,M=2;

int main()
{   
    int i,j,min=INT_MAX;
    
    int sum,sum1;
    
    int w0[N] = {1,2,2,3};
    int w1[N] = {3,1,3,2};
    
    for(i=0;i<N;i++)
    {
        sum=0;
        sum1=0;
        for(j=0;j<i;j++)
        {
            sum+=w0[j];
            sum1+=w1[j];
        }
        for(j=N-1;j>=i;j--)
        {
            sum+=w1[j];
            sum1+=w0[j];
        }
        
        if(sum<sum1)
        {
            if(min>sum)
                min = sum;
        }
        else
        {
            if(min>sum1)
                min = sum1;
        }
    }
    
    cout<<min;
    
    return 0;
}

I tried to explain it using another table below -

But this way I can only find min value for 2 workers. I need help to to understand the approach for more than 2 workers.

Can there also be a DP solution possible for this?


回答1:


The best way I can think to solve this is using recursion. I would implement this by having a list of unusable workers and a running sum passed to each call, and a global variable of minimum value.

This would also work best if you had a matrix of values. So like matrix[0] = {1, 2, 3}; matrix[1] = {3, 4, 5}. I haven't hardcoded a matrix in a while so please forgive me if the syntax is a little off.

So, using global variables for the matrix this would look something like

int matrix[m][n];
int runningMinimum = INT_MAX; //set the runningMinimum to max so any value compared will be lower
void minimum(int i, vector<int> bannedWorkers, int currentWorker, int sum){
    //test the end condition here
    if (i == n-1){//last column
        if (sum < runningMinimum){runningMinimum = sum;}
        return; //we want to return at the end, whether it's found the new lowest value or not
   
    //if we're not at the end, we need to move one step to the right for all possible workers
    for (int j = 0; j < m; j++){//For each worker
        
        //check to see if the worker is no longer allowed to work
        bool isBanned = false
        for (int k = 0; k < bannedWorkers.size(); k++){
            if (bannedWorkers[k] == j) isBanned = true;
        }
        if(!isBanned){
            if (j == currentWorker){
                minimum(i+1, bannedWorkers, currentWorker, sum+matrix[j][i])
            }else{
                vector<int> newBannedWorkers = bannedWorkers; //Make sure to copy to a new vector
                newBannedWorkers.push_back(currentWorker);
                minimum(i+1, newBannedWorkers, j, sum + matrix[j][i])
            }
        }
    }
    return; //after we've checked every option we want to end that call
}

This is a rough, untested idea but it should give you a solid start. Hope it helps!




回答2:


Probably not the best approach if the number of workers is large, but easy to understand and implement I think. I would:

  1. get a list all the possible combination with repetition of W, for example using the algorithm in https://www.geeksforgeeks.org/combinations-with-repetitions/ . This would give you things like [[W1,W3,W2,W3,W1],[W3,W5,W5,W4,W5]...

  2. Discard combinations where workers are not continuous (loop through the lists counting the times each worker appears in total and the times it appears continuously, if its different then discard the list)

  3. Use the filtered list of lists to check times using the table and keep the minimum one

A possible way to discard lists could be

bool isValid=true;
for (int kk = 0; kk < workerOrder.Length; kk++)
    {    
        int state=0;
        for (int mm = 0; mm < workerOrder.Length; mm++)
        {
            if (workerOrder[mm] == kk && state == 0) { state = 1; } //it has appeard
            if (workerOrder[mm] != kk && state == 1 ) { state = 2; } //it is not contious
            if (workerOrder[mm] == kk && state == 2) { isValid = false; break; } //it appeard again
        }
        if (isValid==false){break;}
    }


来源:https://stackoverflow.com/questions/62604843/finding-the-minimum-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!