题目来源
2023第五届CCPC河南省赛赛题 :E.矩阵游戏
cf链接 :2023 CCPC Henan Provincial Collegiate Programming Contest E.矩阵游戏
样例
text1输入:
1
3 3 1
000
001
?00
text1输出:
1
text2输入:
1
3 3 2
000
001
??0
text2输出:
2
思路
- 先考虑三维,前两维 i, j 表示行列,第三维表示剩余替换?的次数,显然dp[500][500][1000]会爆,则要考虑优化维度。
- 优化参考01背包问题的优化,去掉第一维,枚举x的时候倒序。
- 千万不要忘了先对第一个数做处理,mp(1, 1) = ‘1’,mp(1, 1) = ‘?’ && x 两种情况需要分别将dp数组的对应状态初始化为1。
- 由于是多组测试用例,在开始时重置dp数组不然会出现莫名其妙的错误。
AC代码
#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define INF 0x3f3f3f3f
using namespace std;
int n, m, x;
int dp[510][1010];
char mp[510][510];
void solve()
{
//读入
cin >> n >> m >> x;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
cin >> mp[i][j];
//有多组测试用例,一定要重置dp数组
for(int i = 0; i <= m; i ++)
for(int j = 0; j <= x; j ++)
dp[i][j] = 0;
//对(1, 1)处理
if(mp[1][1] == '1')
for(int i = 0; i <= x; i ++)
dp[1][i] = 1;
if(mp[1][1] == '?')
for(int i = 1; i <= x; i ++)
dp[1][i] = 1;
for(int i = 1; i <= n; i ++) { //1 ~ n
for(int j = 1; j <= m; j ++) { //1 ~ m
for(int k = x; k >= 0; k --) { //key倒序枚举 x ~ 0
if(mp[i][j] == '1') //当前点是 1
{
if(i - 1 > 0)
dp[j][k] = dp[j][k] + 1; //dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j][k] + 1);
if(j - 1 > 0)
dp[j][k] = max(dp[j][k], dp[j - 1][k] + 1); //dp[i][j][k] = max(dp[i][j][k], dp[i][j - 1][k] + 1);
}
else if(mp[i][j] == '0')//当前点是 0
{
// if(i - 1 > 0)
// dp[j][k] = dp[j][k]; //dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j][k]);
if(j - 1 > 0)
dp[j][k] = max(dp[j][k], dp[j - 1][k]); //dp[i][j][k] = max(dp[i][j][k], dp[i][j - 1][k]);
}
else if(mp[i][j] == '?')//当前是 ?
{
if(i - 1 > 0 && k)
dp[j][k] = max(dp[j][k], dp[j][k - 1] + 1); //dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j][k - 1] + 1);
if(j - 1 > 0 && k)
dp[j][k] = max(dp[j][k], dp[j - 1][k - 1] + 1); //dp[i][j][k] = max(dp[i][j][k], dp[i][j - 1][k - 1] + 1);
// 当k为0,同当前点是‘0’一样处理
if(j - 1 > 0 && !k)
dp[j][k] = max(dp[j][k], dp[j - 1][k]); //dp[i][j][k] = max(dp[i][j][k], dp[i][j - 1][k]);
}
}
}
}
//得到1最多的状态(即答案)一定在走到右下角的所有状态中,第二维0 ~ x中取max
int ans = 0;
for(int i = 0; i <= x; i ++) ans = max(ans, dp[m][i]);
cout << ans << endl;
}
int main()
{
int _ = 1;
cin >> _;
while(_--) solve();
return 0;
}