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;
    }
}
posted @ 2025-05-21 17:09  Marinaco  阅读(15)  评论(0)    收藏  举报
//雪花飘落效果