最近競技プログラミングのAtCoderを始めました。
まだまだ初心者です。
問題の点数的に300まではなんとか解けるのですが、400を越えてくると途端にわからなくなる。
今はとにかく過去問を解いて、解法を体に覚えさせています。
解いた記録を残していこうと、今後Qiitaに書いていこうと思います。
初回はこちらの問題。
最大でも6行×6列、それぞれの行と列に対して選択か未選択の2通りとして2^12=4096通り。全探索しても問題ないと考えました。
再帰関数を作って、1行もしく1列を選んで選択か未選択で次の行か列に再帰します。
全ての行と列が終わったら黒いマスを数えてKと等しいなら数え上げます。
自分はbitsetを使い、黒マスなら1、それ以外なら0として計算しました。
黒マスを数え上げるのにbitsetならcount()で一発なので楽です。
自分のソースコードは以下となります。
言語はC++(GCC 9.2.1)でAtCoderのコードテストで確認しています。
# include <bits/stdc++.h>
using namespace std;
int H, W, K;
int count(bitset<36> c, int h, int w) {
int result = 0;
if (h == H && w == W) {
result = c.count() == K ? 1 : 0;
} else if (h == H) {
result += count(c, h, w+1);
for (int i = 0; i < H; i++) {
c.reset(i * W + w);
}
result += count(c, h, w+1);
} else {
result += count(c, h+1, w);
for (int i = 0; i < W; i++) {
c.reset(h * W + i);
}
result += count(c, h+1, w);
}
return result;
}
int main() {
cin >> H >> W >> K;
string s;
bitset<36> c;
for (int i = 0; i < H; i++) {
cin >> s;
for (int j = 0; j < W; j++) {
if (s[j] == '#') c.set(i * W + j);
}
}
cout << count(c, 0, 0) << endl;
}