The Specials Menu LightOJ - 1025

The Specials Menu LightOJ - 1025

题意:在给定的字符串中删去一些字符,使其成为回文串(不能全部都删)。求方案数。

方法:常规的区间dp。ans[i][j]表示在i到j的串中删去一些使得成为回文串的方案数。

对于长度为1的串,显然只有1种方法(只保留自身)。

对于长度大于1的串:

可以删去最左侧字符(方案数ans[i+1][j]),也可以删去最右侧字符(方案数ans[i][j-1])。初步的答案也就是这两者相加。但是这两者有重复的部分,就是ans[i+1][j-1],需要再减去。

如果第i个字符和第j个相同,那么又多了两种选择,第一种是只保留左右两个(1种),第二种是去掉左右两个(ans[i+1][j-1])。

错误原因:

1. 忘开longlong

2. (本地)并不明白删去最左侧和最右侧的字符得到的方案的重叠部分是哪个。看了题解以后瞬间理解。

3. (本地,更早)当成与POJ-1141相同的,然而事实上完全不同

 1 #include<cstdio>
 2 #include<cstring>
 3 typedef long long LL;
 4 LL T,TT,len;
 5 char s[100];
 6 LL ans[110][110];
 7 LL get(LL l,LL r)
 8 {
 9     if(l>r)        return 0;
10     if(l==r)    return 1;
11     if(ans[l][r])    return ans[l][r];
12     LL i,sum=get(l+1,r)+get(l,r-1)-get(l+1,r-1);
13 //    for(i=l;i<r;i++)
14 //        sum+=get(l,i)+get(i+1,r);
15 //***1.删左边get(l+1,r)或删右边get(l,r-1),重复的是get(l+1,r-1);2.左右都删,或只保留左右(要求左右相同)
16     if(s[l]==s[r])    sum+=get(l+1,r-1)+1;
17     return ans[l][r]=sum;
18 }
19 int main()
20 {
21     scanf("%lld",&T);
22     for(TT=1;TT<=T;TT++)
23     {
24         scanf("%s",s+1);
25         len=strlen(s+1);
26         memset(ans,0,sizeof(ans));
27         printf("Case %lld: %lld\n",TT,get(1,len));
28     }
29     return 0;
30 }
posted @ 2017-10-27 21:19  hehe_54321  阅读(129)  评论(0编辑  收藏  举报
AmazingCounters.com