SRM 259 DIV1 Hard CardRemover
問題
3文字のアルファベット大文字が書かれたカードが何枚かある(cards)。
隣接する3つのカードの左右を選び、それらに共通する文字が2つ以上あるならば真ん中のカードを消すことができる。
カードを消せる最大枚数を求めよ
- 2 <= |cards| <= 50
コメント
最大値を判定に使うのはいいなあ
コード
#include <string> #include <vector> #include <cstring> #define mset(m,v) memset(m,v,sizeof(m)) #define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i)) #define rer(i,l,u) for(int (i)=(int)(l);(i)<=(int)(u);++(i)) #define each(it,o) for(__typeof((o).begin()) it = (o).begin(); it != (o).end(); ++ it) using namespace std; bool ok[55][55]; int dp[55][55]; struct CardRemover { int rec(int l, int u) { if(dp[l][u] != -1) return dp[l][u]; int r = 0; rer(i, l+1, u-1) { int s1 = rec(l, i), s2 = rec(i, u); if(s1 + s2 + 1 == u - l - 1 && ok[l][u]) r = max(r, s1 + s2 + 1); else r = max(r, s1 + s2); } return dp[l][u] = r; } int calculate(vector <string> cards) { int n = cards.size(); rep(i, n) rep(j, n) { int x = 0; each(k, cards[i]) x += cards[j].find(*k) != -1; ok[i][j] = x >= 2; } mset(dp, -1); return rec(0, n-1); } };