Reading, processing and counting an array setting limits
Here are some things that may help you improve your code.

Eliminate unused variables

Within main, the variables i, BestA and BestB are declared and some of them set, but they are otherwise unused.  They should be omitted from the program.

Don't abuse the comma operator

This line doesn't really need a comma operator:

bestA = A, bestB = B, bestMin = Min;


It should instead be three separate statements, or (if you follow the previous advice) reduced to a single one involving bestMin.

Don't cast the return from malloc

The return value from malloc or calloc is a void * and does not need an explicit cast.  See this question for a thorough discussion of the reasons not to, but for me the most compelling reason is that it's simply not needed.

Use const where practical

In your sum_array routine, the values in the array are never altered, which is just as it should be.  You should indicate that fact by declaring it like this:

int sum_array(const int* array, int cnt)


Use pointers rather than indexing for speed

Pointers are generally a faster way to access elements than using index variables.  Speed may not a particular goal in this program but it's useful to know anyway.  For example, your sum_array routine could be written like this:

int sum_array(const int* array, int cnt)
{
    int res;
    for ( res = 0; cnt; --cnt)
        res += *array++;
    return res;
}


Check return values for errors

The calls fopen, fscanf and malloc can each fail.  You must check the return values to make sure they haven't or your program may crash (or worse) when given malformed input or due to low system resources.  Rigorous error handling is the difference between mostly working versus bug-free software.  You should strive for the latter.

Consider separating I/O from the algorithm

The I/O is done first, and then the input values are processed to find the answer.  Consider separating those into to separate functions which would both make your program cleaner and also allow for better automated testing (such as automatically generating random values and then checking that the algorithm does the right things).

Reconsider your algorithm

Right now, the sums are recalculated many times, but this isn't strictly necessary. As you iterate through the combinations, the partitioning only moves by one value.  So what you could do instead would be to keep the three sums ProfitA, ProfitB and ProfitC and then just add and subtract the particular value that moves from one brother to another.

I've done some reading and it appears to me that the best you can do for complexity is \$\mathcal{O}(N^3)\$
See this question and the many links from it to explain that.

Think about negative numbers

While the problem states that the shop generates profit each day, it doesn't necesarily mean that every time period is profitable.  This suggests that some of the time periods could be associated with negative numbers.  If we use this input:

8
-5 6 1 4 -9 3 1 2


the program reports a max value of 1, which is correct, but you should verify that it is correct for any possible set of numbers. 

Consider adding an "early bailout"

If it ever occurs that ProfitA == ProfitB == ProfitC (as with the values in the previous point) this must be the answer (do you see why?) so the program could exit early with that correct answer.

Eliminate return 0

You don't need to explicitly provide a return 0; at the end of main -- it's created implicitly by the compiler.