Old Zhao's post
Abstract:
The sum of all positive integers that divide sum into N. Each positive integer k must meet the following requirements: min <= k <= max.
The N integers can be repeated. However, because of the addition exchange rate, 1 + 2 and 2 + 1 are repeated.
Non-recursion is not easy.
I slept in the cold last night and had a stomachache early in the morning. I woke up after 4 o'clock.
Sorry, this is an inspiration.
Finally, it took me half an hour to write down the core idea.
Daqing sent a news post as early as Zhao, but did not expect to officially start writing and encountered some problems. Fortunately, it finally solved them.
Core Ideas:
Use a work array to record the status of each location
1. Minimum allocation
2. Maximum number of assignments
3. Remaining allocation count
In fact, it is also a recursive idea. After the first allocation, the remainder is still a decomposition problem, but the total number of allocations and the number of items have changed.
For example, the working array of sum = 10, n = 4, min = 1, max = 5 and the initial split array are as follows:
Split result Array |
|
1 |
1 |
3 |
5 |
|
|
|
|
|
|
Minimum Current Position |
|
1 |
1 |
3 |
5 |
Maximum current position |
|
2 |
2 |
4 |
5 |
Remaining allocation count |
|
9 |
8 |
5 |
0 |
Another core is to use a flag to point to the rightmost subscript that does not reach the maximum allocation number in the nested loop.
Use this flag to repeatedly execute the loop multiple times to achieve the iteration effect.
Public String printdivision (INT sum, int N, int min, int max)
{< br> // defines the return variable
string result;
stringbuilder builder = new stringbuilder ();
// determine the input validity
If (Min * n> sum | max * n result = "no solution \ n ";
else
{< br> // defines the split array
// from left to right represents each split result of the output expression, that is, the current value
int [] arr = new int [N];
// Define the work Array
// 1st rows represent the minimum value of each digit
// 2nd rows represent the maximum value of each digit
// Row 3rd indicates the sum of accumulated data to the current position.
Int [,] arrwork = new int [3, N];
// Define the maximum value of the temporary Calculation
Int maxvalue;
// Local value to be allocated
Int subsum = sum;
// Initialize the work Array
For (INT I = 0; I <n; I ++)
{
// Obtain the maximum value after position I
Maxvalue = max * (N-I-1 );
// Allowed minimum value at position I
Arrwork [0, I] = maxvalue> = subsum? Min: subsum-maxvalue;
// Maximum allowed value at position I
Arrwork [1, I] = subsum/(n-I );
// Except the last one, all other locations are initialized with the minimum value, and the last one is initialized with the maximum value.
Arr [I] = I <n-1? Arrwork [0, I]: arrwork [1, I];
// Accumulate existing allocation results
Subsum-= arr [I];
// Save the accumulated result to the work Array
Arrwork [2, I] = subsum;
}
// Add the initial allocation to the output
Builder. append (string. Join ("+", array. convertall <int, string> (ARR, convert. tostring )));
Builder. append ("\ n ");
// Excellent. The starting point for this variable sign to be rearranged
Int startpoint = N-2;
// Generate all remaining split results
// Reset the number of assignments from the second to the last position until the end of the first position on the left.
// In addition, because of the relationship between the flag variables, the For Loop will be executed much more frequently than shown on the surface.
For (INT I = n-2; I> = 0; I --)
{
// From the minimum value corresponding to position I plus 1 and then the maximum value from the cycle to the current position
// Change the allocation quantity and accumulative count of the current location.
// This is not recommended in standard cases. Program Not a good coding style
// Here is because a few variables are less involved for (ARR [I] ++, arrwork [2, I] --; arr [I] <= arrwork [1, I]; arr [I] ++, arrwork [2, I] --)
{
// The number of assignments for the current location has changed, and the subsequent locations are reassigned below
Subsum = arrwork [2, I];
Min = arr [I];
For (Int J = I + 1; j <n; j ++)
{
// Obtain the maximum value after position J
Maxvalue = max * (N-J-1 );
// allowed minimum value at position j
// calculate the theoretical minimum value based on the number of pending Operations
arrwork [0, j] = maxvalue> = subsum & subsum-maxvalue
// If the theoretical minimum value is smaller than the number on the left, use the number on the left.
Arrwork [0, J] = arrwork [0, J]> Min? Arrwork [0, J]: min;
// Maximum value allowed at position J
Arrwork [1, J] = subsum/(n-j );
// Except the last one, all other locations are initialized with the minimum value, and the last one is initialized with the maximum value.
Arr [J] = j <n-1? Arrwork [0, J]: arrwork [1, J];
// Accumulate existing allocation results
Subsum-= arr [J];
// Save the accumulated result to the work Array
Arrwork [2, J] = subsum;
// When a position does not reach the maximum value, the next reset start point starts from here. Here is the key point for forming recursion-like
If (ARR [J] <arrwork [1, J])
Startpoint = J;
}
// Reset the start point
I = startpoint;
// Complete a decomposition and Output
Builder. append (string. Join ("+", array. convertall <int, string> (ARR, convert. tostring )));
Builder. append ("\ n ");
}
}
Result = builder. tostring ();
}
Return result;
}
Thank you for watching it.
PS: source code
The source code has been updated, and the dragonpig'sAlgorithmAnd correct my originalCode
Times statistics and Time Detection added
According to the dragonpig idea, the code for getting the remaining arrangement can be simplified as follows:
For (Int J = I + 1; j <n; j ++)
{
// Maximum value allowed at position J
Arrwork [1, J] = subsum/(n-j );
// Calculate and determine the value of the current position
Arr [J] = math. Max (Min, subsum-Max * (N-J-1); // This is the main difference.
// Accumulate existing allocation results
Subsum-= arr [J];
// Save the accumulated result to the work Array
Arrwork [2, J] = subsum;
// When a position does not reach the maximum value, the next reset start point will start from here
If (ARR [J] <arrwork [1, J])
Startpoint = J;
}
It is indeed quite concise.