C♯の勉強

C♯4.0 で TopCoder の過去問を解きます。

TopCoder SRM611: ElephantDrinkingEasy

象が水を飲むときは、一番近いものを選ぶ。つまりそれぞれの象について、水を飲む場合はどこまで鼻を伸ばすかは一意に決まっている。

上側の象と下側の象が水を飲むかどうかは、\(2^{2n}\) 通り。上下の象が鼻を伸ばすかどうかが決まれば、左右の象がそれぞれ水を飲めるかどうかは一意に決まる。

よって上下の象が水を飲む飲まないパターンを全て試せばよい。\( O(n^2*2^{2n}) \)

public class ElephantDrinkingEasy {
    public int maxElephants(string[] map) {
        int n = map.Length;
        var topWater = new int[n];
        var bottomWater = new int[n];
        for (int i = 0; i < n; i++) {
            topWater[i] = bottomWater[i] = -1;
            for (int j = 0; j < n; j++) {
                if (map[j][i] == 'Y') {
                    if (topWater[i] == -1) topWater[i] = j;
                    bottomWater[i] = j;
                }
            }
        }
        int ans = 0;
        for (int topBit = 0; topBit < (1 << n); topBit++) {
            for (int bottomBit = 0; bottomBit < (1 << n); bottomBit++) {
                var existNose = new bool[n, n];
                int drinkableElephantNum = 0;
                for (int i = 0; i < n; i++) {
                    var topElephant = (topBit & (1 << i)) != 0;
                    var bottomElephant = (bottomBit & (1 << i)) != 0;
                    if (topElephant && topWater[i] != -1) {
                        drinkableElephantNum++;
                        for (int row = 0; row <= topWater[i]; row++) {
                            existNose[row, i] = true;
                        }
                    }
                    if (bottomElephant && bottomWater[i] != -1) {
                        if (topElephant && topWater[i] == bottomWater[i]) continue;
                        drinkableElephantNum++;
                        for (int row = bottomWater[i]; row < n; row++) {
                            existNose[row, i] = true;
                        }
                    }
                }
                for (int row = 0; row < n; row++) {
                    // left elephant
                    for (int col = 0; col < n; col++) {
                        if (existNose[row, col]) break;
                        existNose[row, col] = true;
                        if (map[row][col] == 'Y') {
                            drinkableElephantNum++;
                            break;
                        }
                    }
                    // right elephant
                    for (int col = n - 1; col >= 0; col--) {
                        if (existNose[row, col]) break;
                        existNose[row, col] = true;
                        if (map[row][col] == 'Y') {
                            drinkableElephantNum++;
                            break;
                        }
                    }
                }
                ans = Math.Max(ans, drinkableElephantNum);
            }
        }
        return ans;
    }
}