[USACO07OPEN]便宜的回文Cheapest Palindrome/ [USACO15OPEN]回文的路径Palindromic Paths
字串S长M,由N个小写字母构成。欲通过增删字母将其变为回文串,增删特定字母花费不同,求最小花费。
题目描述见上
显然 这是一道区间DP
从两头DP,枚举长度啥的很套路了。具体细节请参见代码qwq
#include<iostream> #include<cstdio> #include<cstring> #define re register int #define maxn 2000+5 #define maxn1 3000+5 int val[maxn],dp[maxn1][maxn1],val1,val2; char ch[maxn1],temp[3]; using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)) { x=(x<<3)+(x<<1)+ch-'0'; ch=getchar(); } return x*f; } int main() { int n,m; memset(dp,0x3f,sizeof(dp));//必须要初始化 n=read(); m=read(); scanf("%s",ch+1); for(re i=1;i<=n;i++) { cin>>temp[0]; val1=read(); val2=read(); val[temp[0]-'a']=min(val1,val2); //易得从中间插入或删除是等效的 } for(re i=1;i<=m;i++) { dp[i][i]=0; if(ch[i]==ch[i+1]) dp[i][i+1]=0; } for(re len=0;len<=m;len++) //len必须从0枚举 //否则会少算情况(连样例都过不了QAQ) for(re i=1;i<=m;i++) { int j=len+i; int x1=ch[i-1]-'a'; int x2=ch[j+1]-'a'; if(x1==x2) dp[i-1][j+1]=min(dp[i-1][j+1],dp[i][j]); dp[i-1][j]=min(dp[i-1][j],dp[i][j]+val[x1]); dp[i][j+1]=min(dp[i][j+1],dp[i][j]+val[x2]); //每种状态都需要算一遍 //因为不知道会从哪个扩展 } cout<<dp[1][m]; return 0; }
某一天,FJ从农场的左上角走到右下角,当然啦,每次他只能往右或者往下走一格。FJ把他走过的路径记录下来。现在,请你把他统计一下,所有路径中,回文串的数量(从前往后读和从后往前读一模一样的字符串称为回文串)。
题目描述见上
显然
这道题和上一道题并没有什么关系(放到这里只是因为都是奶牛题+都有回文)
滚动数组优化dp
#include<bits/stdc++.h> #define re register int #define LL long long #define mod 1000000007 #define maxn 500+5 using namespace std; LL ans; LL f[maxn][maxn]; char field[maxn][maxn]; inline int read() { int x=0; char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar(); } return x; } inline void write(LL x) { if(x>9) write(x/10); putchar(x%10+'0'); } int n; int main() { n=read(); for(re i=1;i<=n;i++) for(re j=1;j<=n;j++) cin>>field[i][j]; if(field[1][1]!=field[n][n]) { write(0); return 0; } f[1][1]=1; for(re i=3;i<=n+1;i++) for(re j=i-1;j>=1;j--) for(re k=i-1;k>=1;k--) { if(field[j][i-j]==field[n+k-i+1][n-k+1]) f[j][k]=(f[j][k]+f[j-1][k]+f[j][k-1]+f[j-1][k-1])%mod; else f[j][k]=0; } for(re i=1;i<=n;i++) ans=(ans+f[i][i])%mod; write(ans); return 0; }
We're the lovers above the city.