lightoj 1025 The Specials Menu (dp)

来源:互联网 发布:ajax实例java类代码 编辑:程序博客网 时间:2024/05/22 08:15

题面

题意

给出一个,可以去掉若干个字符,使它变为回文串的方法有几种.

方法

可以发现,任何一种操作都可以通过不断进行以下三种得到:
1.去掉第一个.dp[i][j]+=dp[i+1][j]
2.去掉最后一个.dp[i][j]+=dp[i][j-1]
3.两边都不去掉(在两端相同的情况下)dp[i][j]+=dp[i+1][j-1]
注意,一二操作同时进行时有重叠部分(dp[i+1][j-1]),相加时要减去.
且再进行三操作时+1(仅有i,j两点组成的字符串)
故最终的方法为:

#define ll long longll dfs(ll u,ll v){    if(v<=u)    {        if(u==v) return 1;        return 0;    }    if(dp[u][v]!=-1) return dp[u][v];    ll res=0;    res+=dfs(u+1,v)+dfs(u,v-1);    if(ch[u]==ch[v]) res++;    else res-=dfs(u+1,v-1);    dp[u][v]=res;    return res;}

代码

#include<bits/stdc++.h>#define ll long longusing namespace std;ll T,TT,dp[70][70];char ch[70];ll dfs(ll u,ll v){    if(v<=u)    {        if(u==v) return 1;        return 0;    }    if(dp[u][v]!=-1) return dp[u][v];    ll res=0;    res+=dfs(u+1,v)+dfs(u,v-1);    if(ch[u]==ch[v]) res++;    else res-=dfs(u+1,v-1);    dp[u][v]=res;    return res;}int main(){    ll i,j;    cin>>T;    TT=T;    while(T--)    {        scanf("%s",ch+1);        memset(dp,-1,sizeof(dp));        printf("Case %lld: %lld\n",TT-T,dfs(1,strlen(ch+1)));    }}
原创粉丝点击