您的位置:首页 > 产品设计 > UI/UE

POJ 1141 Brackets Sequence 动态规划

2010-12-15 23:48 330 查看
在刘汝佳黑书上有详细的解析,自己明天这两种算法自己实现一下,作为对动态规划的深入理解学习

先转一个题解http://blog.163.com/leyni@126/blog/static/16223010220103155534476/?fromdm&fromSearch&isFromSearchEngine=yes

问题:括号匹配问题。给出一个由括号组成字符串,加最少的括号使之匹配。

思路:
设f[i][j]为从i到j这段字串达到匹配所需最少括号数。
初始状态:f[i][i] = 1;
状态转移:
f[i][j] = min{f[i + 1][j - 1 | s[i]与s[j]匹配],f[i + 1][j] | s[i]为左括号,f[i][j - 1] | s[i]为右括号,min{f[i][k]+f[k][j]}}

#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;
const int MAX = 102;
char s[MAX];
int f[MAX][MAX], path[MAX][MAX], n;
void print(int l, int r){
    if (l > r) return;
    if (l == r){
        if (s[l] == '(' || s[l] == ')') cout<<"()"; else cout<<"[]";
    }else if (path[l][r] == -1){
        cout<<s[l]; print(l + 1, r - 1); cout<<s[r];
    }else if (path[l][r] == -2){
        cout<<s[l]; print(l + 1, r);
        if (s[l] == '(') cout<<")"; else cout<<"]";
    }else if (path[l][r] == -3){
        if (s[r] == ')') cout<<"("; else cout<<"[";    
        print(l, r - 1); cout<<s[r];
    }else{
        print(l,path[l][r]);
        print(path[l][r] + 1, r);
    }
}
int main(){
    while(gets(s) != NULL){
        n = strlen(s);        
        memset(f, 0, sizeof(f));
        for (int i = 0; i <= n; i++) f[i][i] = 1;
        for (int k = 1; k < n; k++)
        for (int i = 0; i < n - k; i++){
            int j = i + k; f[i][j] = INT_MAX;
            
            if (s[i] == '(' && s[j] == ')' || s[i] == '[' && s[j] == ']')
				if (f[i + 1][j - 1] < f[i][j]){
					f[i][j] = f[i + 1][j - 1];
					path[i][j] = -1;
				}
				if (s[i] == '(' || s[i] == '[') if (f[i + 1][j] + 1 < f[i][j]){
					f[i][j] = f[i + 1][j] + 1;
					path[i][j] = -2;
				}
				if (s[j] == ')' || s[j] == ']') if (f[i][j - 1] + 1 < f[i][j]){
					f[i][j] = f[i][j - 1] + 1;
					path[i][j] = -3;
				}
				for (int l = i; l < j; l++) if (f[i][l] + f[l + 1][j] < f[i][j]){
					f[i][j] = f[i][l] + f[l + 1][j];
					path[i][j] = l;
				}
        }
        print(0, n - 1);
        cout<<endl;
    }
    return 0;
}


后来按照刘汝佳黑书上面的动态规划算法写了一个可以计算最小变化次数的算法

但在输出规则序列上遇到了难题,望大牛指点

//下面是按照黑书上面的递归算法
#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;

const int MAX = 300;
char s[MAX];
bool calculated[MAX][MAX] = {false};
int dp[MAX][MAX];
int min(int a,int b){
	return a>b?b:a;
}
int bracket(int i,int j){
	int ans = 100000000;
	if (calculated[i][j])
	{
		return dp[i][j];
	}
	if (i > j)
	{
		return 0;
	}
	else if (i == j)
	{
		return 1;
	}
	else{
		if ((s[i] == '(' && s[j] == ')') ||
			(s[i] == '[' && s[j] == ']'))
		{
			ans = min(ans,bracket(i+1,j-1));	
		}
		if ((s[i] == '(' && s[j] != ')') ||
			(s[i] == '[' && s[j] != ']'))
		{
			ans = min(ans,bracket(i+1,j-1)+1);
		}
		if ((s[i] != '(' && s[j] == ')') ||
			(s[i] != '[' && s[j] == ']'))
		{
			ans = min(ans,bracket(i+1,j)+1);
		}
		for (int k = i;k <= j-1;k++)
		{
			ans = min(ans,bracket(i,k) + bracket(k+1,j));
		}
		dp[i][j] = ans;
		calculated[i][j] = true;
	}
	return ans;
}
int main(){
	while(cin>>s){
		int len = strlen(s);
		cout<<bracket(0,len-1)<<endl;
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: