poj 1141 dp解法
题目网址:http://poj.org/problem?id=1141
此题是经典dp,解法和算法导论的矩阵链乘法相似,用矩阵链乘法中加括号的方法搜索搜有括号的匹配方法,然后用递归的方法算出加括号数的最小值。
设i是搜索起点,j是终点 dp(i,j)=min{dp(i,k)+dp(k+1,j)}; k从i遍历到j-1。然后用c[][]记录下取得最小值时的分割点,根据分割点再用递归输出结果。
a[]中存放输入的字符串
注意一点if(a[i]==a[j]),并不表示min{dp(i,j)}==min{dp(i+1,j-1)}, "()()"就是一个反例,因此在dp(i,j)中if(a[i]==a[j]),dp(i,j)和dp(i+1,j-1)都要判断执行
用k[][]记忆最小值,提升效率
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char a[202];
int b[202],c[202][202],k1[202][202];
int dp(int i,int j)
{
int i1,min=214748364,x,y;
if(i>j)
return 0;
if(i==j)
{
return 1;
}
else if(a[i]=='('&&a[j]==')'||a[i]=='['&&a[j]==']')
{
min=dp(i+1,j-1);
c[i][j]=-1;
}
if(i==j)
{
return 1;
}
else
{
for(i1=i;i1<j;i1++)
{
if(k1[i][i1]==-1)x=dp(i,i1);else x=k1[i][i1];
if(k1[i1+1][j]==-1)y=dp(i1+1,j);else y=k1[i1+1][j];
if(min>x+y)
{
min=x+y;
c[i][j]=i1;
}
}
}
k1[i][j]=min;
return min;
}
void print(int i,int j)
{
if(i>j)
return;
if(i==j)
{
if(a[i]=='('||a[i]==')')
printf("()");
else
printf("[]");
}
else if(c[i][j]==-1)
{
if(a[i]=='(')
{
printf("(");
print(i+1,j-1);
printf(")");
}
else
{
printf("[");
print(i+1,j-1);
printf("]");
}
}
else
{
print(i,c[i][j]);
print(c[i][j]+1,j);
}
}
int main(int argc, char** argv) {
int k,i,x,y,q,min;
char s[102];
memset(k1,-1,sizeof(k1));
scanf("%s",a);
k=strlen(a);
min=dp(0,k-1);
print(0,k-1);
printf("\n");
return (EXIT_SUCCESS);
}