CSU 1657 Ways(bfs)

来源:互联网 发布:java反射的应用 编辑:程序博客网 时间:2024/06/09 19:50

题目链接:【CSU 1657】

有一个n*n的正整数矩阵,要你求一条从第一行第一列的格子到第n行第n列的路,使得你走过的格子里面的数乘起来的值末尾的零的个数最小。输出最小个数。

统计并记录一格2的个数以及5的个数,搜索到第i行第j列时,记录以下四个数据:

1、dp[i][j][0][0]:2比较少时2的个数

2、dp[i][j][0][1]:2比较少时5的个数

3、dp[i][j][1][0]:5比较少时2的个数

4、dp[i][j][1][1]:5比较少时5的个数

#include <iostream> #include <algorithm>#include <cstdio>#include <cstring>#include <string>#include <queue>using namespace std;int a[1010][1010][2], f[4][2] = {0,1,1,0,0,-1,-1,0};int vis[1010][1010], n;int dp[1010][1010][2][2];struct node{int x, y;}s, e;int bfs(){memset(vis, 0, sizeof(vis));memset(dp, 0x3f3f3f3f, sizeof(dp));queue<node>q;s.x=1, s.y=1;if(a[1][1][0]<=a[1][1][1]){ dp[1][1][0][0] = a[1][1][0]; dp[1][1][0][1] = a[1][1][1];}else {dp[1][1][1][0] = a[1][1][0];dp[1][1][1][1] = a[1][1][1];}vis[1][1]=1, q.push(s);while(!q.empty()){s=q.front(), q.pop();for(int i=0; i<4; i++){e.x = s.x+f[i][0];e.y = s.y+f[i][1];if(e.x<1||e.x>n||e.y<1||e.y>n) continue;for(int k=0; k<2; k++){int n2 = dp[s.x][s.y][k][0]+a[e.x][e.y][0];int n5 = dp[s.x][s.y][k][1]+a[e.x][e.y][1];if(n2<=n5 && dp[e.x][e.y][0][0]>n2){dp[e.x][e.y][0][0] = n2;dp[e.x][e.y][0][1] = n5;if(!vis[e.x][e.y]) {vis[e.x][e.y]=1, q.push(e);}}else if(n2>n5 && dp[e.x][e.y][1][1]>n5){dp[e.x][e.y][1][0] = n2;dp[e.x][e.y][1][1] = n5;if(!vis[e.x][e.y]){vis[e.x][e.y]=1, q.push(e);}}}}}return min(dp[n][n][0][0], dp[n][n][1][1]);}int main(){while(~scanf("%d", &n)){int x;for(int i=1; i<=n; i++){for(int j=1; j<=n; j++){scanf("%d", &x);int num2=0, num5=0;while(x%2==0) num2++, x/=2;while(x%5==0) num5++, x/=5;a[i][j][0] = num2;a[i][j][1] = num5;}}printf("%d\n", bfs());}return 0;}/*55 2 7 2 52 6 5 3 25 8 5 2 12 5 5 2 61 2 3 5 9*/


0 0