题意:
给定一个二维数组,求从左上角走到右下角得到的数,末尾0的个数最小值(每次向右或向下,边走边乘)
对于任意一条路径,尾0的个数是该路径上cnt2与cnt5之中的较小值,min(cnt2,cnt5)
那就分别对2和5求一遍简单DP,最后再取最小
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define dbg(x) cout << #x << "=" << x << endl;
//#define int ll
// DP : 求从(1,1) 到 (n,n) 的路径乘积数目中末尾0的个数最小的数目
// 求2,5的因子数目的最小值
// 对于求得的某一条路径,如果是2最小路径,这条路不可能存在5的数目更大,否则答案在取min的时候会取5最小路径
// 所以对2和5分别进行简单的DP最终取min
int b[1005][1005][2];
signed main() {
ios::sync_with_stdio(0);
cin.tie(nullptr), cout.tie(nullptr);
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
int x,x1;
cin >> x;
x1 = x;
while (x%2 == 0) {b[i][j][0]++;x/=2;}
while (x1%5 == 0) {b[i][j][1]++;x1/=5;}
}
}
for (int k = 0; k <= 1; k++) {
for (int i = 1; i <= n; i++) {
b[1][i][k] += b[1][i-1][k];
b[i][1][k] += b[i - 1][1][k];
}
}
for (int k = 0; k <= 1; k++) {
for (int i = 2; i <= n; i++) {
for (int j = 2; j <= n; j++) {
b[i][j][k] += min(b[i-1][j][k],b[i][j-1][k]);
}
}
}
cout << min(b[n][n][0],b[n][n][1]);
return 0;
}