実行時間制限: 2 sec / メモリ制限: 1024 MB / Difficulty: 446
問題概要
棟のビルが等間隔に一列に並んでおり、手前から 番目のビルの高さは である。次の条件をともに満たすようにいくつかのビルを選んで電飾で飾るとき、最大でいくつのビルを選ぶことができるか求めよ。なお、ちょうど1つのビルを選んだときは条件を満たすとみなす。
- 選んだビルたちは高さが等しい。
- 選んだビルたちは等間隔に並んでいる。
制約
- 入力は全て整数。
考察
以下のような dp テーブル (dp<map<int, int>>
) を用意して、動的計画法により解く。
- 手前から 番目のビルを含み、間隔が で高さが のビルを選んでいくときの最大選択数
遷移は以下のようになる。
- 各 に対して、ビル が含まれるグループを見ていく。 の場合はビル は選べないのでスキップするとして、そうでないとき、
- に が含まれるとき、 のグループにビル を追加することができるので、 と遷移する。
- そうでないとき、ビル の2つで新たにグループを作ることになるので、 と遷移する。
- 上の2つの判定後、
ans = max(ans, dp[j][d])
で更新する。
コード
#include <bits/stdc++.h> using namespace std; #define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++) template <typename T> inline bool chmax(T &a, T b) { return ((a < b) ? (a = b, true) : (false)); } // ======================================== // int main() { int N; cin >> N; vector<int> H(N); rep(i, 0, N) cin >> H[i]; vector<map<int, int>> dp(N); int ans = 1; rep(i, 0, N) { rep(j, 0, i) { if (H[j] == H[i]) { int d = i - j; if (dp[j].contains(d)) { dp[i][d] = dp[j][d] + 1; } else { dp[i][d] = 2; } chmax(ans, dp[i][d]); } } } cout << ans << endl; }
実装時間: 15分