AtCoder

ABC358 C問題(Popcorn)を解く

AtCoder_ABC358_C

AtCoder が提供しているABC(AtCoder Beginner Contest)358 C問題をC++とPythonで解いてみました。ABC358は、2024年6月15日21:00に実施されました。

AtCoder の紹介はこちらに、プログラミングの方針はこちらに記事があります。

C問題 Popcorn(Difficulty : 273)

問題の詳細は、リンク先をご覧ください。

ABC358 C問題 Popcorn

どのポップコーン売り場で買うか全探索します。AtCoder Problems による Difficulty は 273 でした。

解答案

ポップコーン売り場の数 $N$ の上限は、10 です。このため、すべてのポップコーン売り場の組み合わせ(最大 $2^{10}$ 通り)について調べることができます。bit全探索という方法を使います。

C++ プログラム例(ABC358C)

コードの補足をします。

  • 変数 bit を 0 から $2^N$ 未満まで調べます。この値が、ポップコーン売り場の組み合わせを表します。
    • 下位 i ビット目が 1 であれば、i 番目のポップコーン店で購入します。
  • 変数 bit から、購入するポップコーン店が決まります。その店の組み合わせで、すべての味が購入できるかを調べます。それぞれの店の味をビットORで計算して、$M$ ビットがすべてセットされているか確認します(17ー31行目)。
  • 店の数(ビットの立っている数)の最小値を出力します。

以下が、C++プログラムです。bit全探索のポイントとなる行の背景行を変更しました。

#include <bits/stdc++.h>
using namespace std;

typedef unsigned int uint;

int main()
{
	int n, m;
	cin >> n >> m;
	vector<string> s(n);
	for (int i = 0; i < n; ++i) {
		cin >> s[i];
	}

	int result = n;
	for (uint bit = 0; bit < (1 << n); ++bit) {
		uint t = 0;
		int bit_i = 0;
		for (int i = 0; i < n; ++i) {
			if ((bit & (1 << i)) != 0) {
				++bit_i;
				for (int j = 0; j < m; ++j) {
					if (s[i][j] == 'o') {
						t |= 1 << j;
					}
				}
			}
		}
		if (t == ((1 << m) - 1)) {
			result = min(result, bit_i);
		}
	}

	cout << result << endl;

	return 0;
}

AC(Accepted=正しいプログラム)と判定されました。

Python プログラム例(ABC358C)

Python版も基本的な考え方は同じです。以下がプログラムです。

"""AtCoder Beginner Contest 358 C"""
n, m = map(int, input().split())
s = [input() for i in range(n)]

result = n
for bit in range(1 << n):
    t = 0
    bit_i = 0
    for i in range(n):
        if (bit & (1 << i)) != 0:
            bit_i += 1
            for j, ch in enumerate(s[i]):
                if ch == 'o':
                    t |= 1 << j
    if t == (1 << m) - 1:
        result = min(result, bit_i)

print(result)

こちらも「AC」と判定されました。

最後に

bit全探索を使う典型的な問題でした。タグ「bit全探索」で類題を探すことができます。

引き続き ABC の問題を紹介していきます。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA