http://community.topcoder.com/stat?c=problem_statement&pm=12534&rd=15498
memo[前の前に配置した地点][前に配置した地点]
ある2点間が、ある1つの区間に含まれるかどうかを前もって作っておく。
あとは、今現在着目している地点をこれまで配置した2点と同様の区間にならない様に選んでいく。
const int V = 300 + 10; bool inc[V][V]; bool w[V]; const lli mod = 1000000007; lli memo[V][V]; const int dummy = V - 1; lli rec(int a, int b, int N) { lli& ret = memo[a][b]; if (ret != -1) return ret; lli sum = 1; const int begin = max((a == dummy ? 0 : a + 1), (b == dummy ? 0 : b + 1)); const int end = N - 1; for (int c = begin; c <= end; ++c) { if (inc[a][c]) continue; sum += rec(b, c, N); sum %= mod; } return ret = sum; } class WolfInZooDivOne { public: int count(int N, vector <string> L_, vector <string> R_) { const string L = accumulate(L_.begin(), L_.end(), string("")); const string R = accumulate(R_.begin(), R_.end(), string("")); vector< pair<int, int> > v; { istringstream issL(L); istringstream issR(R); int l, r; while ((issL >> l) && (issR >> r)) { v.push_back(make_pair(l, r)); } } fill(&inc[0][0], &inc[V - 1][V - 1] + 1, false); for (int i = 0; i < N; ++i) { for (int j = i; j < N; ++j) { for (int k = 0; k < v.size(); ++k) { if (v[k].first <= i && j <= v[k].second) { inc[i][j] = true; } } } } fill(&memo[0][0], &memo[V - 1][V - 1] + 1, -1); return rec(dummy, dummy, N); }
0 件のコメント :
コメントを投稿