AtCoder が提供しているABC(AtCoder Beginner Contest)011 C問題をC++で解いてみました。ABC011は、2014年6月21日21:30に実施されました。
AtCoder の紹介はこちらに、プログラミングの方針はこちらに記事があります。
C問題 123引き算(Difficulty : 810(参考値))
問題の詳細は、リンク先をご覧ください。
DPで解ける典型問題です。AtCoder Problems による Difficulty は 810(参考値)でした。
解答案
C++ プログラム例(ABC011C)
DP(動的計画法)で解きます。配列 dp[i]
は、引き算で i
にすることができれば true
、できなければ false
とします。
1から100まで小さい数字から dp[i]
の値を調べます。もし、dp[i]
が true
なら、dp[i-3]
、dp[i-2]
、dp[i-1]
を true
にします(17ー25行目)。ただし、dp[NG1]
、dp[NG2]
、dp[NG3]
は、true
にならず false
にします(26ー28行目)。この操作を100回繰り返します。
与えられる N
が NG1
、NG2
、NG3
と一致している場合があります。13~15行目でこの処理を実装します。以下が、C++プログラムです。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin >> n;
int ng1, ng2, ng3;
cin >> ng1 >> ng2 >> ng3;
vector<bool> dp(n + 1, false);
dp[n] = true;
dp[ng1] = false;
dp[ng2] = false;
dp[ng3] = false;
for (int i = 0; i < 100; ++i) {
for (int j = 1; j <= n; ++j) {
if (dp[j]) {
for (int k = 1; k <= 3; ++k) {
if (j - k >= 0) {
dp[j - k] = true;
}
}
}
}
dp[ng1] = false;
dp[ng2] = false;
dp[ng3] = false;
}
if (dp[0]) {
cout << "YES" << endl;
} else {
cout << "NO" << endl;
}
return 0;
}
AC(Accepted=正しいプログラム)と判定されました。
最後に
DP(動的計画法)を使う典型的な問題です。典型問題を解くことにより習熟度を上げていきたいです。
引き続き ABC の問題を紹介していきます。