問題
AtCoder Beginner Contest 204 D問題
方針
配列の値を集合1と集合2に分け、各総和の差が最小となるような時の、両集合の最大値を求める。
正解コード
こちらは、dp[i][j] := 「i番目までの要素を見た時に、総和をjとすることは可能か?」というdpテーブルを作ることで実装しました。
C++
1#include <bits/stdc++.h> 2#include <math.h> 3using namespace std; 4#define ll long long 5 6/* import vector from standard input */ 7vector<ll> import_vector(ll n) { vector<ll> li = {}; for (ll i = 0; i < n; i++) { ll j; cin >> j; li.push_back(j); } return li; } 8 9/* max(a, b) */ 10ll larger(ll a, ll b) { if (a >= b) { return a; } else { return b; } } 11 12/* sum */ 13ll total(vector<ll> li) { ll ans = 0; for (ll i = 0; i < li.size(); i++) { ans += li.at(i); } return ans; } 14 15void solve() { 16 ll N; cin >> N; 17 vector<ll> A = import_vector(N); 18 19 vector<vector<bool>> dp = {}; 20 for (ll i = 0; i < N; i++) { 21 vector<bool> cand = {}; 22 for (ll j = 0; j <= total(A); j++) { 23 cand.push_back(false); 24 } 25 dp.push_back(cand); 26 } 27 28 dp.at(0).at(A.at(0)) = true; 29 for (ll i = 0; i < N; i++) { 30 dp.at(i).at(0) = true; 31 } 32 33 for (ll i = 1; i < N; i++) { 34 for (ll j = 0; j <= total(A); j++) { 35 if (j >= A.at(i)) { 36 dp.at(i).at(j) = (dp.at(i - 1).at(j - A.at(i)) || dp.at(i - 1).at(j)); 37 } 38 else { 39 dp.at(i).at(j) = dp.at(i - 1).at(j); 40 } 41 } 42 } 43 44 vector<bool> check = dp.at(N - 1); 45 ll faster = 0; 46 for (ll j = 0; j <= total(A); j++) { 47 if (2 * j <= total(A) && check.at(j)) { 48 faster = j; 49 } 50 } 51 52 ll slower = total(A) - faster; 53 cout << larger(slower, faster) << endl; 54} 55 56int main() { 57 solve(); 58}
不正解コード
方針は全く同じですが、dp[i][j] := 「i番目までの要素を見た時に、総和をjとする選び方の場合の数は何通りか?」というdpテーブルを組みました。
C++
1#include <bits/stdc++.h> 2#include <math.h> 3using namespace std; 4#define ll long long 5 6/* import vector from standard input */ 7vector<ll> import_vector(ll n) { vector<ll> li = {}; for (ll i = 0; i < n; i++) { ll j; cin >> j; li.push_back(j); } return li; } 8 9/* max(a, b) */ 10ll larger(ll a, ll b) { if (a >= b) { return a; } else { return b; } } 11 12/* sum */ 13ll total(vector<ll> li) { ll ans = 0; for (ll i = 0; i < li.size(); i++) { ans += li.at(i); } return ans; } 14 15void solve() { 16 17 ll N; cin >> N; 18 vector<ll> A = import_vector(N); 19 20 vector<vector<ll>> dp = {}; 21 for (ll i = 0; i < N; i++) { 22 vector<ll> cand = {}; 23 for (ll j = 0; j <= total(A); j++) { 24 cand.push_back(0); 25 } 26 dp.push_back(cand); 27 } 28 29 dp.at(0).at(A.at(0)) = 1; 30 for (ll i = 0; i < N; i++) { 31 dp.at(i).at(0) = 1; 32 } 33 34 for (ll i = 1; i < N; i++) { 35 for (ll j = 0; j <= total(A); j++) { 36 if (j >= A.at(i)) { 37 dp.at(i).at(j) = dp.at(i - 1).at(j - A.at(i)) + dp.at(i - 1).at(j); 38 } 39 else { 40 dp.at(i).at(j) = dp.at(i - 1).at(j); 41 } 42 } 43 } 44 45 vector<ll> check = dp.at(N - 1); 46 ll faster = 0; 47 for (ll j = 0; j <= total(A); j++) { 48 if (2 * j <= total(A) && check.at(j) > 0) { 49 faster = j; 50 } 51 } 52 53 ll slower = total(A) - faster; 54 cout << larger(slower, faster) << endl; 55} 56 57int main() { 58 solve(); 59}
質問
両者は基本的には全く同一のアルゴリズムで組み立てられていて、違いといえば「可能か?」の部分を「何通りか?」に変えただけで、これは後者の値が0より大きい時前者の可能であるということに対応すると考えておりました。しかし、ジャッジでは複数個のテストケースにおいて不正解が出る結果となりました。一体どの部分が起因してこのようになってしまうのでしょうか。素人質問にて恐縮ですが、ご教授のほど何卒よろしくお願い申し上げます。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。