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);
}

  

posted @ 2011-08-17 20:33  枫月寒  阅读(421)  评论(0编辑  收藏  举报