Div2 250 - RainyRoad
The problem has very short solution. Also it is possible solve it using more familiar approach (using dfs or bfs).
public class RainyRoad {
public String isReachable(String[] road) {
for (int i = 0; i < road[0].length(); ++i) {
if (road[0].charAt(i) == 'W' && road[1].charAt(i) == 'W')
return "NO";
}
return "YES";
}
}
Div2 950 - MagicalSquare
I wrote solution with very big complexity O(N ^ 6). But it passed all tests.
public class MagicalSquare {
String R[], C[];
String A[][] = new String[3][3];
Long dp[][][][] = new Long[3][51][51][51];
long rec(int l, int i1, int i2, int i3) {
if (l == 3) {
if (i1 == C[0].length() && i2 == C[1].length() && i3 == C[2].length()) return 1;
return 0;
}
if (dp[l][i1][i2][i3] != null) return dp[l][i1][i2][i3];
String s1 = C[0].substring(i1);
String s2 = C[1].substring(i2);
String s3 = C[2].substring(i3);
String cur = R[l];
int len = cur.length();
long res = 0;
for (int i = 0; i <= len; ++i) {
String t3 = cur.substring(i);
if (!s3.startsWith(t3)) continue;
for (int j = 0; j <= i; ++j) {
String t1 = cur.substring(0, j);
String t2 = cur.substring(j, i);
if (!s2.startsWith(t2)) continue;
if (!s1.startsWith(t1)) continue;
res += rec(l + 1, i1 + t1.length(), i2 + t2.length(), i3 + t3.length());
}
}
return dp[l][i1][i2][i3] = res;
}
public long getCount(String[] rowStrings, String[] columnStrings) {
this.R = rowStrings;
this.C = columnStrings;
return rec(0, 0, 0, 0);
}
}
I wrote simple brute force solution with O(N^6) complexity which surprisingly do not became time limit. Of course there is more faster solution which uses inclusion–exclusion principle. It has O(N^4) complexity.
public class DropCoins {
public int getMinimum(String[] board, int K) {
int res = Integer.MAX_VALUE;
int n = board.length;
int m = board[0].length();
for (int i1 = 0; i1 < n; ++i1)
for (int i2 = i1; i2 < n; ++i2)
for (int j1 = 0; j1 < m; ++j1)
for (int j2 = j1; j2 < m; ++j2) {
int cnt = 0;
for (int i = i1; i <= i2; ++i)
for (int j = j1; j <= j2; ++j)
if (board[i].charAt(j) != '.')
++cnt;
if (cnt != K) continue;
int t1 = i1;
int t2 = n - 1 - i2;
int t = Math.min(2 * t1 + t2, 2 * t2 + t1);
t1 = j1;
t2 = m - 1 - j2;
t += Math.min(2 * t1 + t2, 2 * t2 + t1);
res = Math.min(res, t);
}
if (res == Integer.MAX_VALUE) return -1;
return res;
}
}
Div1 525 - Rumor
import java.io.*;
import java.util.*;
public class Rumor {
int n, know, g[], mask;
int res = Integer.MAX_VALUE;
int check(int use) {
int knowA = know, knowB = know;
int giveA = 0, giveB = 0;
int cnt = 0;
while (knowA != mask || knowB != mask) {
if (++cnt >= res) return -1;
int newKnowA = 0, newKnowB = 0;
for (int i = 0; i < n; ++i) {
if (testBit(giveA, i) && testBit(giveB, i)) continue;
if (!testBit(knowA, i) && !testBit(knowB, i)) continue;
String s = "";
if (!testBit(giveA, i) && testBit(knowA, i)) s += 'a';
if (!testBit(giveB, i) && testBit(knowB, i)) s += 'b';
if (s.length() == 0) continue;
char ch;
if (s.length() == 2) {
if (testBit(use, i)) ch = s.charAt(0);
else ch = s.charAt(1);
} else ch = s.charAt(0);
if (ch == 'a') {
newKnowA |= g[i];
giveA |= 1 << i;
} else {
newKnowB |= g[i];
giveB |= 1 << i;
}
}
if ((knowA | newKnowA) == knowA && (knowB | newKnowB) == knowB) return -1;
knowA |= newKnowA;
knowB |= newKnowB;
}
return cnt;
}
private boolean testBit(int use, int i) {
return ((use >> i) & 1) == 1;
}
public int getMinimum(String knowledge, String[] graph) {
n = knowledge.length();
mask = (1 << n) - 1;
g = new int[n];
for (int i = 0; i < n; ++i) {
if (knowledge.charAt(i) == 'Y') {
know |= 1 << i;
}
for (int j = 0; j < n; ++j) {
if (graph[i].charAt(j) == 'Y')
g[i] |= 1 << j;
}
}
for (int use = 0; use < (1 << n); ++use) {
int t = check(use);
if (t == -1) continue;
res = Math.min(res, t);
}
if (res == Integer.MAX_VALUE) return -1;
return res;
}
}
Div1 950 - MonochromePuzzle
public class MonochromePuzzle {
public int getMinimum(String a[]) {
int n = a.length;
for (int i = 0; i < n; ++i) {
int c = 0;
for (int j = 0; j < n; ++j) {
if (a[i].charAt(j) != a[j].charAt(i)) return -1;
if (a[i].charAt(j) == '#') ++c;
}
if (c != 3) return -1;
}
int p[] = null;
for (int i = 1; i < n; ++i) {
p = check(a, 0, i);
if (p != null) break;
}
if (p == null) return -1;
int res = Integer.MAX_VALUE;
for (int tt = 0; tt < 3; ++tt) {
for (int i = 0; i < n / 2; ++i) {
int x = get(p);
res = Math.min(x, res);
rshift(p, 0, n / 2);
lshift(p, n / 2, n);
}
reverse(p, 0, n);
for (int i = 0; i < n / 2; ++i) {
int x = get(p);
res = Math.min(x, res);
rshift(p, 0, n / 2);
lshift(p, n / 2, n);
}
reverse(p, 0, n / 2);
reverse(p, n / 2, n);
for (int i = 0; i < n / 2; ++i) {
int x = get(p);
res = Math.min(x, res);
rshift(p, 0, n / 2);
lshift(p, n / 2, n);
}
reverse(p, 0, n);
for (int i = 0; i < n / 2; ++i) {
int x = get(p);
res = Math.min(x, res);
rshift(p, 0, n / 2);
lshift(p, n / 2, n);
}
if (n != 8) break;
int np[] = new int[8];
np[0] = p[0];
np[1] = p[3];
np[2] = p[4];
np[3] = p[7];
np[4] = p[6];
np[6] = p[2];
np[7] = p[1];
np[5] = p[5];
for (int i = 0; i < 8; ++i) p[i] = np[i];
}
return res;
}
private void reverse(int p[], int lo, int hi) {
int n = (hi - lo) / 2;
for (int i = 0; i < n; ++i) {
int tmp = p[lo + i];
p[lo + i] = p[hi - i - 1];
p[hi - i - 1] = tmp;
}
}
private void lshift(int p[], int lo, int hi) {
int tmp = p[lo];
for (int i = lo; i + 1 < hi; ++i) {
p[i] = p[i + 1];
}
p[hi - 1] = tmp;
}
private void rshift(int p[], int lo, int hi) {
int tmp = p[hi - 1];
for (int i = hi - 1; i > 0; --i) {
p[i] = p[i - 1];
}
p[0] = tmp;
}
private int get(int p[]) {
int n = p.length;
boolean use[] = new boolean[n];
int res = 0;
for (int i = 0; i < n; ++i) {
if (use[i]) continue;
int cur = i;
int c = 0;
while (!use[cur]) {
use[cur] = true;
++c;
cur = p[cur];
}
if (c >= 2) res += c - 1;
}
return res;
}
private int[] check(String a[], int u, int v) {
if (a[u].charAt(v) != '#') return null;
int n = a.length;
int p[] = new int[n];
int left = 0, right = n - 1;
p[left++] = u;
p[right--] = v;
boolean use[] = new boolean[n];
use[u] = use[v] = true;
int pu = u, pv = v;
for (int k = 1; k < n / 2; ++k) {
boolean ok = false;
for (int i = 1; !ok && i < n; ++i) {
if (use[i]) continue;
for (int j = 1; !ok && j < n; ++j) {
if (use[j] || i == j) continue;
if (a[i].charAt(j) != '#') continue;
if (a[i].charAt(pu) != '#') continue;
if (a[j].charAt(pv) != '#') continue;
if (k == n / 2 - 1) {
if (a[i].charAt(u) != '#') continue;
if (a[j].charAt(v) != '#') continue;
}
ok = true;
p[left++] = i;
p[right--] = j;
use[i] = use[j] = true;
pu = i;
pv = j;
}
}
if (!ok) return null;
}
return p;
}
}