每日一dp(3)——POJ 1141 Brackets Sequence

来源:互联网 发布:呱呱社区软件 编辑:程序博客网 时间:2024/04/26 11:22


/************************************************************************//* 区间动态规划问题一般都是考虑,对于每段区间,他们的最优值都是由几段更小区间的最优值得到,是分治思想的一种应用,将一个区间问题不断划分为更小的区间直至一个元素组成的区间,枚举他们的组合 ,求合并后的最优值。区间上dp,即把整个区间划分为一个个的小区间,在小区间内dp求出最优值,然后把这些小区间合并以后就是整个区间的最优值。设F[i,j](1<=i<=j<=n)表示区间[i,j]内的数字相加的最小代价最小区间F[i,i]=0(一个数字无法合并,∴代价为0)每次用变量k(i<=k<=j-1)将区间分为[i,k]和[k+1,j]两段For p:=1 to n do // p是区间长度,作为阶段。 for i:=1 to n do // i是穷举的区间的起点beginj:=i+p-1; // j是 区间的终点,这样所有的区间就穷举完毕if j>n then break; // 这个if很关键。for k:= i to j-1 do // 状态转移,去推出 f[i,j]f[i , j]= max{f[ i,k]+ f[k+1,j]+ w[i,j] } end; 区间型dp dp[i][j] 表示使 i 到 j 全部匹配最少需要添加的括号个数。转移方程:dp[i][j] = min(dp[i][j], dp[i][k] + dp[i+1][k])dp[i][i]=1;过程中则首先判断i与j是否匹配,完后划分*//************************************************************************/#include<iostream>#include<cstring>#include <string.h>using namespace std;#define maxn 100+5int dp[maxn][maxn];int flag[maxn][maxn];char str[maxn];int length;int judge(int a,int b){if( (str[a]=='(' && str[b]==')'  ) || (str[a]=='[' && str[b]==']')   )return 1;return 0;}void fdp(){}void print(int a,int b){if(a>b) return ;if(a == b)  //    {          if(str[a] == '[' || str[a] == ']') printf("[]");          else printf("()");      }  else if(flag[a][b]==-1){printf("%c",str[a]);print(a+1,b-1);printf("%c",str[b]);}else{print(a,flag[a][b]);print(flag[a][b]+1,b);}}int main(){while(gets(str) != NULL){length=strlen(str);int i,l,r,k;//这部分如果封装成函数fdp则会超时,看来以后尽量写在主函数中memset(dp,0,sizeof(dp));for(i=0;i<length;i++)dp[i][i]=1;for(l=1;l<length;l++)for(i=0;i+l<length;i++){r=i+l;dp[i][r]=0x7fffffff;if(judge(i,r))dp[i][r]=dp[i+1][r-1],flag[i][r]=-1;//意思是这两个可以匹配,不用添加for(k=i;k<r;k++)if(dp[i][r]>dp[i][k]+dp[k+1][r])dp[i][r]=dp[i][k]+dp[k+1][r],flag[i][r]=k;}//print(0,length-1);printf("\n");}return 0;}


0 0
原创粉丝点击