pro:给定N*M的矩阵,现在让你在每一行删去一个位置,然后形成新N*(M-1)的矩阵,问有多少种不同的新的矩阵。需要满足相邻行删去的位置不大于K。

(题目是01矩阵,其实任意矩阵都可以做,本题算法里只关心相邻的是否相同。

sol:dp[i][j]表示从上到下删,删到第i行,第i行删去第j列的不同矩阵方案数。 

        再用一个same数组去重,same[i][j]表示dp[i][j]和dp[i][j-1]的共同部分,即a[i][j]=a[i][j-1]的公共来源部分。

一直维护dp和same数组即可。

详解请移步:https://blog.csdn.net/CatDsy/article/details/81876341

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=2010;
const int Mod=998244353;
int dp[maxn][maxn],same[maxn][maxn];
int sum1[maxn][maxn],sum2[maxn][maxn];
char c[maxn][maxn];
int main()
{
    int T,N,M,K,ans;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&N,&M,&K);
        rep(i,1,N) scanf("%s",c[i]+1);
        rep(i,1,M) {
            dp[1][i]=1;
            same[1][i]=(i!=1&&c[1][i]==c[1][i-1]);
            sum1[1][i]=sum1[1][i-1]+dp[1][i];
            sum2[1][i]=sum2[1][i-1]+same[1][i];
        }
        rep(i,2,N){
            rep(j,1,M) {
                dp[i][j]=((sum1[i-1][min(M,j+K)]-sum1[i-1][max(0,j-K-1)])%Mod+Mod)%Mod-((sum2[i-1][min(M,j+K)]-sum2[i-1][max(0,j-K)])%Mod+Mod)%Mod;
                if(dp[i][j]<0) dp[i][j]+=Mod;
                if(j==1||c[i][j]!=c[i][j-1]) same[i][j]=0;
                else same[i][j]=((sum1[i-1][min(M,j+K-1)]-sum1[i-1][max(0,j-K-1)])%Mod+Mod)%Mod-((sum2[i-1][min(M,j+K-1)]-sum2[i-1][max(0,j-K)])%Mod+Mod)%Mod;
                if(same[i][j]<0) same[i][j]+=Mod;
                sum1[i][j]=(sum1[i][j-1]+dp[i][j])%Mod;
                sum2[i][j]=(sum2[i][j-1]+same[i][j])%Mod;
            }
        }
        ans=0;
        rep(i,1,M) ans=((ans+(dp[N][i]-same[N][i])%Mod)%Mod+Mod)%Mod;
        printf("%d\n",ans);
    }
    return 0;
}