给出一个 n∗n 的数字矩阵,现在要从(1,1)点走到(n,n)点,每一步只能朝下 或者朝右走,在走的过程中要将经过格子的数字累乘起来,并使得这个累乘数值 末尾 0 的数量尽可能的少。
编程计算乘积末尾 0 个数的最小值。
我的90分代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct o{
int x,y;
}a[505][505],f[505][505],f2[505][505];
signed main(){
// freopen("matrix1.in","r",stdin);
// freopen("sweet.out","w",stdout);
int t;
cin>>t;
while(t--){
memset(f,0x3f,sizeof(f));
memset(f2,0x3f,sizeof(f2));
int n,ans=LONG_LONG_MAX;
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int x,y,c1=0,c2=0;
cin>>x,y=x;
for(;x>0&&x%5==0;x/=5)c1++;
for(;y>0&&y%2==0;y/=2)c2++;
a[i][j].x=c1,a[i][j].y=c2;
}
}
f[1][1].x=a[1][1].x,f[1][1].y=a[1][1].y;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i*j==1)continue;
if(i==1)f[i][j].x=f[i][j-1].x+a[i][j].x,
f[i][j].y=f[i][j-1].y+a[i][j].y;
else if(j==1)f[i][j].x=f[i-1][j].x+a[i][j].x,
f[i][j].y=f[i-1][j].y+a[i][j].y;
else if(f[i-1][j].x<f[i][j-1].x||(f[i-1][j].x==f[i][j-1].x&&f[i-1][j].y<f[i][j-1].y))
f[i][j].x=f[i-1][j].x+a[i][j].x,
f[i][j].y=f[i-1][j].y+a[i][j].y;
else f[i][j].x=f[i][j-1].x+a[i][j].x,
f[i][j].y=f[i][j-1].y+a[i][j].y;
}
}
ans=min(f[n][n].x,f[n][n].y);
f2[1][1]=a[1][1],f2[1][1].y=a[1][1].y;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i*j==1)continue;
if(i==1)f2[i][j].x=f2[i][j-1].x+a[i][j].x,
f2[i][j].y=f2[i][j-1].y+a[i][j].y;
else if(j==1)f2[i][j].x=f2[i-1][j].x+a[i][j].x,
f2[i][j].y=f2[i-1][j].y+a[i][j].y;
else if(f2[i-1][j].y<f2[i][j-1].y||(f2[i-1][j].y==f2[i][j-1].y&&f2[i-1][j].x<f2[i][j-1].x))
f2[i][j].x=f2[i-1][j].x+a[i][j].x,
f2[i][j].y=f2[i-1][j].y+a[i][j].y;
else f2[i][j].x=f2[i][j-1].x+a[i][j].x,
f2[i][j].y=f2[i][j-1].y+f2[i][j].y;
}
}
cout<<min(ans,min(f2[n][n].x,f2[n][n].y))<<"\n";
}
return 0;
}
我的思路:先求出每个数因子5和因子2的个数,用结构体存下来,然后末尾0的个数就是路径上因子5和因子2的个数中的最小值,那就先假设最小值是因子2,那么就用dp就求因子2的最小值,如果因子2一样求5少的一个,再反着用5求一次即可,取最小值即可。
不一定非要调代码,我知道我的代码不咋好看(),能给个hack就行。