F-渝
题目链接:https://ac.nowcoder.com/acm/contest/109904/F
题意:
给定一个从顶至底,底面长度依次增加的三角形01矩阵
试求从(1,1)开始到底面有多少种构造回文串的方案?
思路:
多维dp
由于从上至下不好记录状态,观察到回文串的性质,考虑从三角矩阵中间分别往上,下进行状态转移
记dp[i][j][k]:为从中间开始移动距离为k,上面走到第i列,下面走到了第j列的方案数
因为k一定是从k-1转移得到,可以将k的上界记为2
考虑转移,显然只有当两个横向距离关于中心对称的矩阵值相同时,才可以成为一个方案
注意到上下都可以转移两个点,因此有4个状态需要转移
最终答案为上面为1,下面为j(1<=j<=n)的方案数的累加
由于奇偶性不同会导致回文串的不同性质,所以要分开dp并注意不同的初始化
每次转移都要清空上上个dp数组
可以通过%2或者&1的方式实现
时间复杂度O(nxnxn)(n<=500)
int f[505][505];
int n;
int dp[505][505][2];
int ans;
void solve(){
cin>>n;
rep(i,1,n){
for(int j=1;j<=i;j++){
cin>>f[i][j];
}
}
if(n&1){
int m=(n+1)/2;
for(int i=1;i<=m;i++){
dp[i][i][0]=1;
}
for(int d=1;d<=n/2;d++){
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
dp[j][k][d%2]=0;
}
}
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
if(f[m-d][j]==f[m+d][k]){
dp[j][k][d%2]+=dp[j+1][k][(d-1)%2];
dp[j][k][d%2]+=dp[j+1][k-1][(d-1)%2];
dp[j][k][d%2]+=dp[j][k][(d-1)%2];
dp[j][k][d%2]+=dp[j][k-1][(d-1)%2];
dp[j][k][d%2]%=mod;
}
}
}
}
for(int j=1;j<=n;j++){
ans=(ans%mod+dp[1][j][(n/2)%2]%mod)%mod;
}
cout<<ans<<endl;
}else{
int m=n/2;
for(int j=1;j<=m;j++){
if(f[m][j]==f[m+1][j]){
dp[j][j][0]++;
}
if(f[m][j]==f[m+1][j+1]){
dp[j][j+1][0]++;
}
}
for(int d=1;d<=n/2-1;d++){
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
dp[j][k][d%2]=0;
}
}
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
if(f[m-d][j]==f[m+1+d][k]){
dp[j][k][d%2]+=dp[j+1][k][(d-1)%2];
dp[j][k][d%2]+=dp[j+1][k-1][(d-1)%2];
dp[j][k][d%2]+=dp[j][k][(d-1)%2];
dp[j][k][d%2]+=dp[j][k-1][(d-1)%2];
dp[j][k][d%2]%=mod;
}
}
}
}
for(int j=1;j<=n;j++){
ans=(ans%mod+dp[1][j][(n/2-1)%2]%mod)%mod;
}
cout<<ans<<endl;
}
}

浙公网安备 33010602011771号