【题解】P3049
考试的 B 题。
不难想到 DP。(然鹅我没想到 qwq)
我们先将数组进行一个神奇的处理,以样例为例:
\(a={1,2,3,4}\to a'={1,2,2,3,3,3,4,4,4,4}\)
\(b={4,3,2,0}\to b'={1,1,1,1,2,2,2,3,3}\)
这时就变成了我们熟悉的“编辑字符距离”的问题。P2758 编辑距离
状态转移方程:
dp[i][j] = min(min(dp[i][j - 1] + x, dp[i - 1][j] + y), dp[i - 1][j - 1] + z * abs(a[i] - b[j]))
记得设边界条件。
\(\text{Code}\)
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int MAXN = 1e3 + 5;
int n, x, y, z, lena, lenb;
int a[MAXN], b[MAXN], dp[MAXN][MAXN];
int main()
{
scanf("%d%d%d%d", &n, &x, &y, &z);
for (int i = 1; i <= n; i++)
{
int c, d;
scanf("%d%d", &c, &d);
for (int j = 1; j <= c; j++) //预处理
{
a[++lena] = i;
}
for (int j = 1; j <= d; j++)
{
b[++lenb] = i;
}
}
for (int i = 1; i <= lena; i++) //边界条件
{
dp[i][0] = y * i;
}
for (int i = 1; i <= lenb; i++)
{
dp[0][i] = x * i;
}
for (int i = 1; i <= lena; i++)
{
for (int j = 1; j <= lenb; j++)
{
dp[i][j] = min(min(dp[i][j - 1] + x, dp[i - 1][j] + y), dp[i - 1][j - 1] + z * abs(a[i] - b[j]));
}
}
printf("%d", dp[lena][lenb]);
return 0;
}