(ΦωΦ)<これの答えですよー。目次はここ。
---
問4-4
(ΦωΦ)<再帰
#include <iostream>
#include <algorithm>
using namespace std;
const int mod = 1000;
int n, allsum;
vector<int> m, dp;
// 今までに買った商品たちの定価の合計
int sum_of(int mask) {
int res = 0;
for(int i=0; i<n; i++) {
if(mask>>i & 1) { res += m[i]; }
}
return res;
}
// 買った商品の集合がmask
// そのときの値引きの最大金額を返す
int rec(int mask) {
int &res = dp[mask];
// 何も買ってないので値引きは無い。
if(mask == 0) { return res = 0; }
if(res > 0) { return res; }
// i番目を買う前の時点に話を戻したい
for(int i=0; i<n; i++) {
if(!(mask>>i & 1)) { continue; } // i番目を買ってないから話を戻せない
// i番目を買うときの値引き額は
// "i番目を買う前"の買った商品たちの定価の合計から算出する
res = max(res, rec(mask&~(1<<i)) + min(m[i], sum_of(mask&~(1<<i)) % mod));
}
return res;
}
int main(void) {
scanf("%d", &n);
m.resize(n);
for(int i=0; i<n; i++) {
scanf("%d", &m[i]);
allsum += m[i];
}
dp.resize(1<<n);
int discount = rec((1<<n)-1);
printf("%d\n", allsum-discount);
return 0;
}
(ΦωΦ)<forループ
#include <iostream>
#include <algorithm>
using namespace std;
const int mod = 1000;
int n;
vector<int> m, dp;
int sum_of(int mask) {
int res = 0;
for(int i=0; i<n; i++) {
if(mask>>i & 1) { res += m[i]; }
}
return res;
}
int main(void) {
scanf("%d", &n);
m.resize(n);
int allsum = 0;
for(int i=0; i<n; i++) {
scanf("%d", &m[i]);
allsum += m[i];
}
dp.resize(1<<n, 0);
for(int mask=0; mask<1<<n; mask++) {
for(int i=0; i<n; i++) {
if(mask>>i & 1) { continue; }
int &tmp = dp[mask|(1<<i)];
int val = dp[mask] + min(m[i], sum_of(mask) % mod);
tmp = max(tmp, val);
}
}
int res = allsum - dp[(1<<n)-1];
printf("%d\n", res);
return 0;
}
(ΦωΦ)<おしまい