[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;

}

 
View Code

 


某一天,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;
}
View Code

 

posted @ 2019-04-10 16:46  3200Phaethon  阅读(229)  评论(2编辑  收藏  举报