This question is a classical linear dp question.
The trick to simplfy the question is to preprocess the data with a special discretized method.
We can label the soil with its id and seperate the data just like below:
original array : 1 4 5 6
discretized : 1 2 2 2 2 3 3 3 3 3 6 6 6 6 6 6
The benefits of the above operation is when you calculating the moving cost and illustrating the idea would be easier.
There are total three state:
1. removing soil: dp[i - 1][j] + y
2. adding soil: dp[i][j - 1] + x
3. shifting soil: dp[i - 1][j - 1] + z* abs(a[j] - b[j])
First, studying the removing case. It is pretty obvious, since we dont need a[i] , then just abandon it, thus we need to inherit the i - 1 state with j remain unchanged, we have
dp[i - 1][j] + y.
Second, in the adding case, as we are making the a's array longer to match with the b[j], position i should not move, but making the length of a longer, thus j is moving, and the j comes from j - 1, we have dp[i][j] = dp[i][j - 1] + x.
P.S. the i is not moving is because we dont need to consider about where the i come from, we consider the adding operation from the cost aspect, which already added into the dp[i][j - 1].
Lastm in the shifting case, shifting is just remove a soil from previous landscape and add back the current landscape, with this idea, the state is pretty easy. With removing operation, i - 1, the adding operation j - 1, thus dp[i][j] = dp[i - 1][j - 1] + z* abs(a[i] - a[j]), the original formula of z, is
z * |i - j|, however we already preprocessed the data, it is easy to calculate.
P.S. maybe concern about the correctness of shifting, how to shift the soil from the larger index landscape to the small index landscape? the j is a for loop from 1 to n, which includes all the possible combinations.
dp[i][j] = min(dp[i - 1][j] + y, dp[i][j - 1] + x, dp[i - 1][j - 1] + z * abs(a[i] - b[j]))
there are two cases you have to consider, which is dp[0][i] and dp[i][0], in these cases, the only operation is adding and removing, so, initilize dp[0][i] and dp[i][0] is a must.
for(int i = 1; i <= lena; i++) dp[0][i] = i * x;
for(int i = 1; i <= lenb; i++) dp[i][0] = i * y;
#include <iostream>
#include <cstring>
using namespace std;
int n, x, y, z, lena = 1, lenb = 1;
int a[1005], b[1005];
int dp[1005][1005];
void work(){
cin >> n >> x >> y >> z;
for(int i = 1 , a1, b1; i <= n; i++){
cin >> a1 >> b1;
while(a1--)a[lena++] = i;
while(b1--)b[lenb++] = i;
}
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= lenb; i++)dp[0][i] = i * x;
for(int i = 1; i <= lena; i++)dp[i][0] = i * y;
for(int i = 1; i <= lena; i++){
for(int j = 1; j <= lenb; j++){
dp[i][j] = min(dp[i - 1][j] + y, min(dp[i - 1][j - 1] + z*abs(a[i] - b[j]), dp[i][j - 1] + x));
}
}
cout << dp[lena][lenb] << endl;
}
int main(){
work();
return 0;
}