问题 G: 多少个0
时间限制: 1 Sec 内存限制: 128 MB提交: 192 解决: 40
题目描述
一个n*n的方格,每个格子中间有一个数字是2或者5,现在从方格的左上角走到右下角,每次只能选择向下或者向右移动一格两种移动方式,让所有经过的格子中的数字相乘,求使最后的结果中末尾处0的数字最少。
输入
第一行是一个正整数n(0<n<100)。
接下来n行是一个n*n的矩阵。
输出
一个正整数m,表示最后的结果末尾处最少有x个0。
样例输入
4
2 5 2 5
5 2 5 2
2 5 5 5
2 2 2 2
样例输出
1
刚开始的时候,对这一题的理解不够,认为求0的个数肯定要求最后数的大小。后来才想到,这一题只有2和5,而且每个0都需要一个2和一个5相乘才能得到。所以,这一题只需找两条路径,一条是2的个数最多的,一条是5的个数最多的,然后求两个数的最大值,还有重要的一点就是从点(1,1)到点(n,n)共有n*2-1个点,这样就可以求出相对应的5或2的个数。
例如题目多给的测试数据,从左上角走到右下角2最多的一条路径的个数为6,而5的个数最多的是4,取二者之中的最大者,即2的个数为6,相应的可以求出5的个数2*n-1-6=7-6=1,所以最后0的个数为1。
1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 #define N 105 5 int a[N][N]; 6 int dp2[N][N],dp5[N][N]; 7 int main() 8 { 9 int n,i,j,num; 10 while(cin>>n) 11 { 12 for(i=1; i<=n; i++) 13 for(j=1; j<=n; j++) 14 cin>>a[i][j]; 15 memset(dp2,0,sizeof(dp2)); 16 memset(dp5,0,sizeof(dp5)); 17 for(i=1; i<=n; i++) 18 for(j=1; j<=n; j++) 19 { 20 dp2[i][j] = max(dp2[i-1][j],dp2[i][j-1]); 21 dp5[i][j] = max(dp5[i-1][j],dp5[i][j-1]); 22 if (a[i][j] == 2) 23 dp2[i][j]++; 24 if(a[i][j] == 5) 25 dp5[i][j]++; 26 } 27 num = max(dp2[n][n],dp5[n][n]); 28 cout<<2*n-1-num<<endl; 29 } 30 return 0; 31 }