Moortal Kombat#10292

Moortal Kombat (Çözgüdiň düşündirişi)

Let's run the Floyd – Warshall algorithm on the matrix a_{ij} to determine the shortest time required to replace each letter with any other letter.

Then construct a cost matrix , where cst[i][j]~(1 \le i \le n) represents the minimum number of days needed to change the letter s[i - 1] into the letter .

For convenience in further calculations, we build a matrix that contains the column-wise prefix sums of the cost matrix :

ps[i][j] = cst[i][1] + cst[i][2] + ... + cst[i][j]

Let dp[i][j] denote the minimum number of days required to transform the first letters of the string into a string that satisfies Bessie’s new requirements, with the last letters of the new string being the letter .

We can write the dynamic equations as follows:

cst[i - k + 1][j] + cst[i - k + 2][j] + ... + cst[i][j]

days. This sum can be computed in constant time using the prefix sum array :

cst[i - k + 1][j] + cst[i - k + 2][j] + ... + cst[i][j] = ps[i][j] - ps[i - k][j]

We maintain an auxiliary array , where

mn[i] = min(dp[i][0], dp[i][1], ..., dp[i][m - 1])

Thus, the dynamic programming equation for this case (i \ge k) takes the following form:

dp[i][j] = ps[i][j] - ps[i - k][j] + mn[i - k]

It remains to choose the smaller of the two options for dp[i][j].

The answer to the problem is the value

mn[n] = min(dp[n][0], dp[n][1], ..., dp[n][m - 1])

We don't care which particular letters the new word Bessie ends with.

Example

In this example, the optimal solution is as follows: replace with , then with , and after that replace both 's with . The total cost of the changes is 1 + 4 + 0 + 0 = 5 days, and the resulting string will be .

Using the matrix a_{ij}, we construct the cost matrix . We also compute the matrix .

All values of dp[1][j]~(0 \le j \le 4) will be equal to , since the length of the stripe cannot be less than k = 2. Accordingly, mn[1] = +∞.

Let us now consider the process of computing the values of dp[2][j] (0 ≤ j ≤ 4).

mn[2] = min(dp[2][0], dp[2][1], dp[2][2], dp[2][3] , dp[2][4]) = 1

When computing the values of dp[3][j]~(0 \le j \le 4), the equation

dp[3][j] = ps[3][j] - ps[1][j] + mn[1]

will not be used, since mn[1] = +∞. Therefore, to obtain strips from the first three letters, one can only extend the strips of length two that have already been constructed:

The value of can be obtained in two ways:

or

The second case is more optimal — two letters '' are appended to a two-character string. The value mn[2] = 1 is achieved for the string "", which means the optimal string is "".

Algorithm implementation

Let us define the following arrays:

#define MAXN 100005
#define ALPH 26
int a[ALPH][ALPH], cst[MAXN][ALPH], ps[MAXN][ALPH], dp[MAXN][ALPH], mn[MAXN];

Read the input data.

cin >> n >> m >> k;
cin >> s;
for (i = 0; i < m; i++)
for (j = 0; j < m; j++)
   cin >> a[i][j];

Run the Floyd - Warshall algorithm on the matrix . After it finishes, contains the minimum number of days required to change letter into letter .

for (x = 0; x < m; x++)
for (i = 0; i < m; i++)
for (j = 0; j < m; j++)
  a[i][j] = min(a[i][j], a[i][x] + a[x][j]);

We have m \le 26 letters. Let us construct a cost matrix such that cst[i][j]~(1 \le i \le n) contains the minimum number of days required to change the letter s[i - 1] into letter . The letters in the string are indexed starting from .

For convenience in further computations, we'll build a matrix , which contains the column-wise prefix sums of the cost matrix :

ps[i][j] = cst[i][1] + cst[i][2] + ... + cst[i][j]
for (i = 1; i <= n; i++)
for (j = 0; j < m; j++)
{
  cst[i][j] = a[s[i - 1] - 'a'][j];
  ps[i][j] = ps[i - 1][j] + cst[i][j];
}

Initialize the arrays.

memset(dp, 0x3f, sizeof dp);
memset(mn, 0x3f, sizeof mn);
mn[0] = 0;

We compute the values of the array cells. The letter corresponds to the character s[i - 1]. The letters in variable are numbered from (corresponding to letter '') to m - 1. Intuitively, at each step , Bessie decides:

We choose the cheaper option and save the result in dp[i][j].

We start the loop over from because the first valid stripe can only end at position .

for (i = k; i <= n; i++)
for (j = 0; j < m; j++)
{

We continue the current stripe. The letter s[i - 1] of the original string is changed to . That is:

  dp[i][j] = min(dp[i][j], dp[i - 1][j] + cst[i][j]);

We start a new stripe of letters. We assume that at position a new stripe of exactly (or more) letters ends, consisting of the letter . To do this:

ps[i][j] - ps[i - k][j]
  dp[i][j] = min(dp[i][j], ps[i][j] - ps[i - k][j] + mn[i - k]);

After computing all dp[i][j] for a fixed , we store the best (minimum) value among all in .

  mn[i] = min(mn[i], dp[i][j]);
}

Print the answer.

cout << mn[n] << "\n";