括號匹配 (區間dp)
區間dp
題目大意:給出一個的只有’(‘,’)’,’[‘,’]’四種括號組成的字串,求最多有多少個括號滿足匹配。
題目連結
思路:用dp[i][j]表示區間i~j的最大匹配數,對於dp[i][j] = dp[i + 1][j - 1] + (s[i]和s[j]匹配?2 : 0),開始時dp[i][j]均為0。
程式碼如下:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 1e2 + 100;
char str[maxn];
int dp[maxn][maxn];
int main()
{
while(~scanf("%s", str) && strcmp(str, "end"))
{
memset(dp, 0, sizeof(dp));
int n = strlen(str);
for(int len = 2; len <= n; len++)
{
for(int i = 0; i < n; i++)
{
if(i + len - 1 > n) break ;
int j = i + len - 1;
if((str[i] == '(' && str[j] == ')') || (str[i] == '[' && str[j] == ']'))
{
dp[i][j] = dp[i + 1][j - 1] + 2;
}
else dp[i][j] = dp[i + 1][j - 1];
for (int k = i; k < j; k++)
{
dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j]);
}
}
}
printf("%d\n", dp[0][n - 1]);
}
}
括號匹配升級:
問最少加多少括號,能使其完全匹配。加上個記錄路徑。
比如:( [ ( ] 最少加兩個 變為 ( ) [ () ]
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 1e2 + 100;
const int INF = 0x3f3f3f3f;
char str[maxn];
int dp[maxn][maxn], tag[maxn][maxn];
// tag[i][j]用於記錄區間[i, j]在哪裡斷開
// dp[i][j]表示區間[i, j]最少的不匹配的數量。
void print(int l, int r) {
if(l > r) return ;
if(l == r) {
if(str[l] == '(' || str[r] == ')') printf("()");
else printf("[]");
return ;
}
if(tag[l][r] == -1) {
printf("%c", str[l]);
print(l + 1, r - 1);
printf("%c", str[r]);
}
else {
print(l, tag[l][r]);
print(tag[l][r] + 1, r);
}
}
int main()
{
while(~scanf("%s", str))
{
memset(dp, 0, sizeof(dp));
memset(tag, -1, sizeof(tag));
int n = strlen(str);
if(n == 0) {
printf("\n");
continue;
}
for(int i = 0; i <= n; i++) dp[i][i] = 1; //一個的時候是1
for(int len = 2; len <= n; len++)
{
for(int i = 0; i < n; i++)
{
if(i + len - 1 >= n) break;
int j = i + len - 1;
dp[i][j] = dp[i + 1][j - 1];
if((str[i] == '(' && str[j] == ')') || (str[i] == '[' && str[j] == ']'))
{ }
else dp[i][j] += 2;
//當str[i]與str[j]匹配時,dp[i][j] = dp[i + 1][j - 1]
//不匹配時,加2
for(int k = i; k < j; k++)
{
if(dp[i][j] >= dp[i][k] + dp[k + 1][j]) { //要加=號是因為']('這樣的情況,在沒進第三個for的時候就已經變成了2,[0,1]區間應該被分割開加符號,但是tag記錄不到。
dp[i][j] = dp[i][k] + dp[k + 1][j];
tag[i][j] = k;
}
}
}
}
print(0, n - 1);
printf("\n");
}
}
附紫書上的做法:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 100;
const int inf = 0x3f3f3f3f;
int dp[maxn][maxn], tag[maxn][maxn];
char str[maxn];
bool match(char a, char b) {
if((a == '(' && b == ')') || (a == '[' && b == ']')) return true;
return false;
}
void print(int l, int r) {
if(l > r) return ;
if(l == r) {
if(str[l] == '(' || str[r] == ')') printf("()");
else printf("[]");
return ;
}
if(tag[l][r] == -1) {
printf("%c", str[l]);
print(l + 1, r - 1);
printf("%c", str[r]);
}
else {
print(l, tag[l][r]);
print(tag[l][r] + 1, r);
}
}
int main()
{
gets(str);
int len = strlen(str);
if(len == 0) {
printf("\n");
return 0;
}
for(int i = 0; i < len; i++)
{
dp[i][i] = 1;
}
memset(tag, -1, sizeof(tag));
for(int i = len - 2; i >= 0; i--)
{
for(int j = i + 1; j < len; j++)
{
dp[i][j] = len + 1;
if(match(str[i], str[j])) dp[i][j] = min(dp[i][j], dp[i + 1][j - 1]);
for(int k = i; k < j; k++)
{
if(dp[i][j] > dp[i][k] + dp[k + 1][j])
{
dp[i][j] = dp[i][k] + dp[k + 1][j];
tag[i][j] = k;
}
}
}
}
print(0, len - 1);
printf("\n");
}
相關推薦
括號匹配 (區間dp)
區間dp 題目大意:給出一個的只有’(‘,’)’,’[‘,’]’四種括號組成的字串,求最多有多少個括號滿足匹配。 題目連結 思路:用dp[i][j]表示區間i~j的最大匹配數,對於dp[i][j] = dp[i + 1][j - 1] + (s[i]和s[
括號匹配問題(區間dp)
最小值 很好 nbsp 需要 簡單的 棧模擬 pri tex 什麽 簡單的檢查括號是否配對正確使用的是棧模擬,這個不必再說,現在將這個問題改變一下:如果給出一個括號序列,問需要把他補全成合法最少需要多少步? 這是一個區間dp問題,我們可以利用區間dp來解決,直接看代碼吧!
括號匹配(二)(區間dp)
括號匹配(二)題目描述:給你一個字串,裡面只包含"(",")","[","]"四種符號,請問你需要至少新增多少個括號才能使這些括號匹配起來。如:[]是匹配的([])[]是匹配的((]是不匹配的([)]是
nyoj 15 括號匹配(二)(區間DP)
括號匹配(二) 描述 給你一個字串,裡面只包含"(",")","[","]"四種符號,請問你需要至少新增多少個括號才能使這些括號匹配起來。 如: []是匹配的 ([])[]是匹配的 ((]是不匹
LightOJ - 1422 Halloween Costumes (區間DP)
wan things strong cas book article printf ase con Description Gappu has a very busy weekend ahead of him. Because, next weekend is Ha
POJ 1141 Brackets Sequence (區間DP)
ive bsp rip mes character har typedef som memset Description Let us define a regular brackets sequence in the following way: 1.
Brackets Sequence POJ - 1141 (區間dp)
gif == urn ++ char img ems utc pre Brackets Sequence POJ - 1141 題意:給一個括號序列,問最少添加多少個括號似的原序列匹配,並輸出新序列。 用dp[i][j]表示i到j最少添加幾個括號,flag[i][j]表
Brackets POJ - 2955 (區間dp)
pla clu for eof %d img rac end racket Brackets POJ - 2955 題意:給一個括號序列,問最多有多少個括號是可以配對的。 1 #include<cstdio> 2 #include<algori
Food Delivery ZOJ - 3469 (區間dp)
位置 turn pro pan return isp ive != truct Food Delivery ZOJ - 3469 題意:快遞員送外賣,n個客戶,起始位置為x,速度為v,每個客戶單位時間不滿意度增加hi,問最少增加多少不滿意度。 每一個客戶可能是從左側送到
CSUOJ-1980 不堪重負的數(區間dp)
inline 滿二叉樹 -a ems ext div des button problems 1980: 不堪重負的樹 Submit Page Summary Time Limit: 1 Sec Memory Limit: 128 Mb Subm
POJ 1991 Turning in Homework(區間DP)
clu sin highlight sort stream ret spa 作業 ref 題目鏈接 Turning in Homework 考慮區間DP f[i][j][0]為只考慮區間[i, j]且最後在a[i]位置交作業的答案。 f[i][j][1]為只考慮區間[
hdu6212 祖瑪(區間DP)
tro 位置 表示 中間 ron i+1 strong 就會 題意 題意 有一個長度為n的01串,我們可以在某個地方插入一個0或者1,那麽如果有連續顏色相同的>=3個,那麽這段就會消去,兩邊的合攏。問將所有01串消去,最少需要插入多少個。(n<=200)
修長城 (區間DP)
urn ret 世紀 log width hide 時間 main gif Time Limit: 1000 ms Memory Limit: 256 MB Description 大家都知道,長城在自然條件下會被侵蝕,因此,我們需要修復。現在是21世紀,
Codeforces 392E Deleting Substrin(區間dp)
read temp put tdi char i+1 void log ++ 題目大意: ? 給定vi,wi,每次可以在wi中選擇一個子段[l,r]滿足:? |wi-wi+1|=1 (l<=i<r)? 2wi-wi-1-wi+1>=0 (l<i<
【Uva10559】Blocks(區間DP)
log turn logs efi read etc body pre 數量 Description 題意:有一排數量為N的方塊,每次可以把連續的相同顏色的區間消除,得到分數為區間長度的平方,然後左右兩邊連在一起,問最大分數為多少。 \(1\leq N\leq200\) S
You Are the One HDU - 4283(區間dp)
eas value script names elf for stdio.h 表示 text You Are the One Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Jav
Topcoder SRM 301 Div2-1000 CorrectingParenthesization(區間DP)
完全 errors 實現 括號 cor ren opc fin 區間dp 題意 給定一個長度為偶數的字符串。這個字符串由三種括號組成。 現在要把這個字符串修改為一個符合括號完全匹配的字符串,改變一個括號的代價為$1$,求最小總代價。 區間DP。令$dp[i
【BZOJ】1260 [CQOI2007]塗色paint(區間dp)
c++ ide hid event pri display pro == spl 題目 傳送門:QWQ 分析 區間dp, 詳見代碼 代碼 /*****************************************
【lightoj-1025】The Specials Menu(區間DP)
.com lightoj 不同 cin mes std 需要 就是 ++ 題目鏈接:http://www.lightoj.com/volume_showproblem.php?problem=1025 【題目大意】 求一個字符串刪去任意字符可以構成多少個不同的回文
POJ 1651 Multiplication Puzzle (區間DP)
contain 個數 ++ %d str poi point return IE Description The multiplication puzzle is