I'm solving the following problem. Here is the problem statement:
You are given a string with wildcards, e.g.
X***Y*Z
. Your goal is to print an input string filling all the wildcards in the given string.You are allowed to write data to the string in blocks of fixed size: character-by-character, you can write contiguous blocks of identical characters of length
2, 3 ... N: X, XX, XXX
, etc. For example:Block: XX, apply to the 2 position in X***Y*Z => X*XXY*Z
It is allowed to overwrite same characters:
Block: XX, apply to the 0 position in X***Y*Z => XX**Y*Z
When you choose the size of block you would like to use, let's say
S
, "preparation" costs occurs:S * L
, where L - some input constant.
Let's say, you picked the size2
(cost is2 * L
), then you are allowed to writeXX
,YY
, andZZ
to the given string.When you write a block of data to the given string, writing cost occurs - some input constant
C
that is independent of the block size. When you choose some block length, e.g.2
, you have to fill all blanks usingblock_size = 2
, you are not allowed to decrease or increase it in the middle of writing. For example, if you write the first piece of data to the given string asXX
, later you are allowed to useYY
andZZ
only. The same with other sizes.Your task is to identify the minimum possible cost to fill all blanks considering costs of writing data and preparing a block.
Let's consider the example above in details. We are given a string
X***Y*Z
,L = 20
,C = 10
. For each option, there are a plenty of variants how to fill blanks.1) We can fill all blanks with a block of size
1
using any characters from{X, Y, Z}
. Thus, total cost is1 * 20 (prepare a block of size 1) + 4 * 10 (fill 4 wildcards) = 60
. Possible results, there are plenty of them:XYXZYXZ, XXXYYZZ ...
2) We can use
block size = 2
. For example: overwriteX*
withXX
,**
withXX
,Y*
withYY
, the total cost is2 * 20 (prepare the block of size 2) + 3 * 10 (perform 3 writing operations to fill all blanks), the total cost is 70
.Example:
Solution 1
Init: X***Y*Z
step1: write XX at 0 => XX**Y*Z
step2: write XX at 1 => XXX*Y*Z
step3: write YY at 3 => XXXYY*Z
step4: write ZZ at 4 => XXXXYYZ
My solution is pretty simple:
- assume a data block's length equals M
- Try to fill a string using DFS
- Compute & update cost if neccessary
- Increment block size, goto 1
It works pretty well but I'm wondering if performance can be better?
Code:
#include <iostream>
using namespace std;
int N = 0;
int L = 0;
int K = 0;
const int max_length = 101;
const int max_value = 1000000;
char s[max_length];
char buf[max_length];
int min (int a, int b) {
return a < b ? a : b;
}
int print_string(char d, int start, int d_size, int depth) {
if (start >= N) return max_value;
if (start + d_size > N) return max_value;
for (int i = start; i < start + d_size; ++i) {
if (buf[i] != '*' && buf[i] != d) return max_value;
}
if (start + d_size == N) return depth;
for (int i = start; i < start + d_size; ++i) { buf[i] = d; }
int res = max_value;
for (int i = start; i < start + d_size; ++i) {
int xc = print_string('X', i+1, d_size, depth+1);
int yc = print_string('Y', i+1, d_size, depth+1);
int zc = print_string('Z', i+1, d_size, depth+1);
res = min(res, min (xc, min (yc, zc)));
}
for (int i = start; i < start + d_size; ++i) { buf[i] = s[i]; }
return res;
}
int compute() {
// we always can solve with m == 1, so there is no point in checking it
// assuming that it is maximum cost
int cost = N * K + 1 * L;
for (int m = 2; m <= N; ++m) {
// cout << "size " << m << '\n';
int xc = print_string('X', 0, m, 1);
int yc = print_string('Y', 0, m, 1);
int zc = print_string('Z', 0, m, 1);
const int steps = min(xc, min(yc, zc));
const int cur = K * steps + L * m;
if (cur < cost) {
cost = cur;
}
}
return cost;
}
int main(int argc, char* argv[]) {
int T = 0;
cin >> T;
for(int t = 1; t <= T; ++t) {
cin >> N;
cin >> L;
cin >> K;
for (int i = 0; i < N; ++i) { cin >> s[i]; buf[i] = s[i]; }
int res = compute();
int exp = 0;
cin >> exp;
cout << "#" << t << " " << res << "; expected = " << exp << '\n';
}
return 0;
}
Data sample:
7
48 10 10
XX****YY*X*ZXX****YY*X*ZXX****YY*X*ZXX****YY*X*Z
260
6 13 8
**X**Y
50
6 13 8
XXX**Z
50
6 13 8
XXX***
50
6 13 8
X*Y*X*
50
5 13 8
ZZZZZ
50
5 13 8
XYZYX
53
Y*X*Z
, you know that max block size would be 3, because you cant fit 4 or more there \$\endgroup\$