c语言中字母相乘,[转载]定义于字母表∑{a,b,c)上的乘法表如表1所示

定义于字母表∑{a,b,c)上的乘法表如表1所示

表1∑乘法表

| a b c

--------

a| b b a

b| c b a

c| a c c

依此乘法表,对任一定义于∑上的字符串,适当加括号表达式后得到一个表达式。例如,对于字符串s[]=bbbba,它的一个加括号表达式为i

(b(bb))(ba)。依乘法表,该表达式的值为a。试设计一个动态规划算法,对任一定义于∑上的字符串s=s[1]x[2]…x[n],计算有多少种不同的加括号方式,使由x导出的加括号表达式的值为a

要求:

输入:输入一个以a,b,c组成的任意一个字符串。

输出:计算出的加括号方式数。

int 一个三位数组, s[100] 用来存 接收的字符串

用于记录一段连续的序列内通过加括号可得到a、b、c的方式数,

然后调用 递归程序 run(0,strlen(s)-1,need);(need 是 我们想要的结果)

,因为每两个字母相乘的结果已给出,所以可通过加和乘运算求出更大长度的字符串得到a、b、c的方式数

dp[i][j][s[need]] 表示 字符串s[i] s[i+1]....s[j]的表达式的值为s[need](s[need] 为

'a','b',或者'c'.) 的方式数;

递归式为:

(0 代表

'a' 1 代表

'b' 2 代表 'c' )

dp[s][t][0]

= dp[s][t][0] + run(s,i,0)*run(i+1,t,2) + run(s,i,1)*run(i+1,t,2) +

run(s,i,2)*run(i+1,t,0);

dp[s][t][1]

= dp[s][t][1] + run(s,i,0)*run(i+1,t,0) + run(s,i,0)*run(i+1,t,1) +

run(s,i,1)*run(i+1,t,1);

dp[s][t][2]

= dp[s][t][2] + run(s,i,1)*run(i+1,t,0) + run(s,i,2)*run(i+1,t,1) +

run(s,i,2)*run(i+1,t,2) ;

最初我吧 dp全部set 成 -1 这样便于记忆化搜索。。。避免重复递归。。。让递归跟递推一样快。

并且思路清楚

只要进来过 就 把 dp[s][t][need]=0; 应为有可能 s到t 值为need 的方法有0个 。

以下是我的程序

#include

#include

char s[100];

int n;

int dp[100][100][3];

int run(int s,int t,int need)

{

if(dp[s][t][need]!=-1)return dp[s][t][need];

int i;

dp[s][t][need]=0;

for(i=s;i

{

if(need==0)

dp[s][t][0]

= dp[s][t][0] + run(s,i,0)*run(i+1,t,2) + run(s,i,1)*run(i+1,t,2) +

run(s,i,2)*run(i+1,t,0);

else if(need==1)

dp[s][t][1]

= dp[s][t][1] + run(s,i,0)*run(i+1,t,0) + run(s,i,0)*run(i+1,t,1) +

run(s,i,1)*run(i+1,t,1);

else

dp[s][t][2]

= dp[s][t][2] + run(s,i,1)*run(i+1,t,0) + run(s,i,2)*run(i+1,t,1) +

run(s,i,2)*run(i+1,t,2) ;

}

return dp[s][t][need];

}

int main()

{

int i;

while(scanf("%s",&s)!=EOF)

{

memset(dp,-1,sizeof(dp));

n=strlen(s);

for(i=0;i

dp[i][i][s[i]-'a']=1;

printf("%dn",run(0,n-1,0));

}

return 0;

}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值