dp[i][j][k]代表从(1,1)移动到(i,j)在最多替换k个?的情况下可以得到的最大分数
可得状态转移方程
dp[i][j][k]=max(dp[i-1][j][k],dp[i][j-1][k])(s[i][j]=='0'||(s[i][j]=='?'&&k==0))
dp[i][j][k]=max(dp[i-1][j][k],dp[i][j-1][k])+1(s[i][j]=='1')
dp[i][j][k]=max(max(dp[i-1][j][k],dp[i][j-1][k]),max(dp[i-1][j][k-1],dp[i][j-1][k-1])+1)(s[i][j]=='?'&&k!=0)
#include <bits/stdc++.h>
#define endl '\n'
#define INF 0x3f3f3f3f
#define ll long long
#define Mirai ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
#define pb push_back
using namespace std;
typedef pair<int, int> PII;
const int N=510,X=1e3+10;
char s[N][N];
int dp[2][N][X];
int T,n,m,x,res;
int main()
{
cin>>T;
while(T--)
{
res=0;
cin>>n>>m>>x;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>s[i][j];
for(int i=0;i<=m;i++)
for(int j=0;j<=x;j++)
dp[0][i][j]=dp[1][i][j]=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=0;k<=x;k++)
if(s[i][j]=='0')dp[i&1][j][k]=max(dp[i-1&1][j][k],dp[i&1][j-1][k]);
else if(s[i][j]=='1')dp[i&1][j][k]=max(dp[i-1&1][j][k],dp[i&1][j-1][k])+1;
else
{
if(k==0)dp[i&1][j][k]=max(dp[i-1&1][j][k],dp[i&1][j-1][k]);
else dp[i&1][j][k]=max(max(dp[i&1][j-1][k],dp[i-1&1][j][k]),max(dp[i&1][j-1][k-1],dp[i-1&1][j][k-1])+1);
}
for(int i=0;i<=x;i++)res=max(res,dp[n&1][m][i]);
cout<<res<<endl;
}
return 0;
}
每次更新只与上次更新有关,所以可以优化第一维数组