(ΦωΦ)<これの答えですよー。目次はここ。
---
問3-2
(ΦωΦ)<再帰 解き方 その1
#include <iostream>
#include <algorithm>
using namespace std;
class OrderOfOperationsDiv2 { public: int minTime(vector<string> s); };
const int inf = 987654321;
int n, m;
vector<int> dp, t;
// 引数: 今まででどの命令を既に実行したか
int rec(int mask) {
if(mask == (1<<n) - 1) { return 0; }
if(dp[mask] != inf) { return dp[mask]; }
int used = 0; // 今まででどのメモリを既に使ったか
for(int i=0; i<n; i++) {
if(mask>>i & 1) { used |= t[i]; }
}
int res = inf;
for(int i=0; i<n; i++) {
if(mask>>i & 1) { continue; }
int k = __builtin_popcount(t[i] & ~used); // t[i]にだけ立ってるビットを調べる
// kが0のときも見に行かないといけない
res = min(res, rec(mask | (1<<i)) + k*k); // i番目の命令をやる
}
return dp[mask] = res;
}
int OrderOfOperationsDiv2::
minTime(vector<string> s) {
n = s.size(), m = s[0].size();
t.assign(n, 0);
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
t[i] |= (s[i][j] - '0') << j;
}
}
dp.assign((1<<20) + 10, inf);
return rec(0);
}
(ΦωΦ)<再帰 解き方 その2
#include <iostream>
#include <algorithm>
using namespace std;
class OrderOfOperationsDiv2 { public: int minTime(vector<string> s); };
const int inf = 987654321;
int n, m;
vector<int> dp, t;
// 引数: 今まででどのメモリを既に使ったか
int rec(int mask) {
if(dp[mask] != inf) { return dp[mask]; }
int res = inf;
for(int i=0; i<n; i++) {
int k = __builtin_popcount(t[i] & ~mask);
if(k == 0) { continue; } // kが0のときはmask == (mask | t[i])なので見に行ってはいけない
res = min(res, rec(mask | t[i]) + k*k); // i番目の命令をやる
}
if(res == inf) { res = 0; }
return dp[mask] = res;
}
int OrderOfOperationsDiv2::
minTime(vector<string> s) {
n = s.size(), m = s[0].size();
t.assign(n, 0);
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
t[i] |= (s[i][j] - '0') << j;
}
}
dp.assign((1<<20) + 10, inf);
return rec(0);
}
---
(ΦωΦ)<for 解き方 その1
#include <iostream>
#include <algorithm>
using namespace std;
class OrderOfOperationsDiv2 { public: int minTime(vector<string> s); };
const int inf = 987654321;
int OrderOfOperationsDiv2::
minTime(vector<string> s) {
int n = s.size(), m = s[0].size();
vector<int> t(n);
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
t[i] |= (s[i][j] - '0') << j;
}
}
vector<int> dp(1<<n, inf);
dp[0] = 0;
for(int mask=0; mask<1<<n; mask++) {
int used = 0;
for(int i=0; i<n; i++) {
if(mask>>i & 1) { used |= t[i]; }
}
for(int i=0; i<n; i++) {
if(mask>>i & 1) { continue; }
int k = __builtin_popcount(t[i] & ~used);
dp[mask|(1<<i)] = min(dp[mask|(1<<i)], dp[mask]+k*k);
}
}
return dp[(1<<n)-1];
}
(ΦωΦ)<for 解き方 その2
#include <iostream>
#include <algorithm>
using namespace std;
class OrderOfOperationsDiv2 { public: int minTime(vector<string> s); };
const int inf = 987654321;
int OrderOfOperationsDiv2::
minTime(vector<string> s) {
int n = s.size(), m = s[0].size();
vector<int> t(n);
int all = 0;
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
t[i] |= (s[i][j] - '0') << j;
}
all |= t[i];
}
vector<int> dp(1<<m, inf);
dp[0] = 0;
for(int mask=0; mask<1<<m; mask++) {
for(int i=0; i<n; i++) {
int k = __builtin_popcount(t[i] & ~mask);
dp[mask|t[i]] = min(dp[mask|t[i]], dp[mask]+k*k);
}
}
return dp[all];
}
(ΦωΦ)<おしまい