ディレクトリ
ブラケット(セクションDP)
タイトル
私たちは、「通常の括弧」シーケンスの次の誘導定義を与えます:
空のシーケンスは、正規ブラケット配列で
sは正規ブラケットシーケンスである場合、(S)及び[S]は、正規ブラケット配列であり、
そしてBは、通常のブラケット配列である場合、ABは、通常のブラケット配列です。
他のシーケンスは、通常の括弧配列である
。例えば、以下の文字列のすべてが定期的にカッコ配列であります:
()、[]、(())、()[]、()()]
次の文字列ではありませんしながら。
(]、()、([)]([(]
文字のブラケットシーケンスはA1A2 ...を考えると、あなたの目標は、sのサブシーケンスである最長の定期的なブラケットシーケンスの長さを見つけることです。それはあなたがそのような1つの≤I1 <I2 <... <イム≤nは、ai1ai2 ...目的は、通常のブラケットシーケンスである指標i1のため、I2、...、イムその最大メートルを見つけたい、です。
初期シーケンスを与えられ([([]])] 、最長正規ブラケットサブシーケンスです[([])]。
入力
入力テストファイルは、複数のテストケースが含まれています。各入力テストケース(、)文字のみを含む単一の行から成る、[、および]。各入力テストは1以上100以下の長さを有するであろう。ファイルの終わりには、単語「終わり」を含む行でマークされ、処理されるべきではありません。
出力
各入力の場合については、プログラムは、単一の行に可能な限り長い正規ブラケットサブシーケンスの長さを印刷しなければなりません。
サンプル入力
((()))
()()()
([])
))(
([] [] [)
エンド
出力例
6
6
4
0
6
問題の意味
括弧の中で最も数が出力に一致させることができます
考え
括弧の数のセル間広い範囲の数を立ち上げ
- セル間では、それが可能であれば一致するエンドDP [I] [j]は= DP [I + 1] [J-1] +2 が最も簡単であるからです。
- しかし、これは最も正確ではありません。
- 用()()のために、DP [2] [3] = 0 なぜなら)(計算のものと一致していないDP [1]〜[4] = 0 + 2 = 2 に等しくなるべきである、間違っている4。
- これは、副走査間隔でなければなりません。実際の最大値であるべきである
DP [1]〜[4] = MAX(DP [1]〜[4]、DP [1] [2] + DP [3] [4])= 4
問題の解決策
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int d[105][105];
int main()
{
char s[105];
while (scanf("%s", s + 1), s[1] != 'e')
{
memset(d, 0, sizeof d);
int len = strlen(s + 1);
//先枚举小区间,因为后面计算大区间时需要使用小区间
for (int l = 0; l <= len; l++)
{
for (int i = 1; i + l - 1 <= len; i++)
{
int j = l + i - 1;
//基本的状态转移
if ((s[i] == '(' && s[j] == ')') || (s[i] == '[' && s[j] == ']'))
{
d[i][j] = d[i + 1][j - 1] + 2;
}
//为了找到真正最大的值,进行扫描。
for (int k = i; k < j; k++)
{
d[i][j] = max(d[i][j], d[i][k] + d[k + 1][j]);
}
}
}
cout << d[1][len] << endl;
}
}