2B The least round way

传送门

题目

There is a square matrix n × n, consisting of non-negative integer numbers. You should find such a way on it that

  • starts in the upper left cell of the matrix;
  • each following cell is to the right or down from the current cell;
  • the way ends in the bottom right cell.

Moreover, if we multiply together all the numbers along the way, the result should be the least "round". In other words, it should end in the least possible number of zeros.

Input

The first line contains an integer number n (2 ≤ n ≤ 1000), n is the size of the matrix. Then follow n lines containing the matrix elements (non-negative integer numbers not exceeding 109).

Output

In the first line print the least number of trailing zeros. In the second line print the correspondent way itself.

Examples
Input
3
1 2 3
4 5 6
7 8 9
Output
0
DDRR

题目大意

给定由非负整数组成的 n×nn \times nn×n 的正方形矩阵,你需要寻找一条路径:

以左上角为起点,每次只能向右或向下走

以右下角为终点 并且,如果我们把沿路遇到的数进行相乘,积应当是最小“round”,换句话说,应当以最小数目的0的结尾.

输入格式

第一行包含一个整数 n ( 2≤n≤10002 \leq n \leq 10002n1000 ),n 为矩阵的规模,接下来的n行包含矩阵的元素(不超过10^9的非负整数).

输出格式

第一行应包含最小尾0的个数,第二行打印出相应的路径(译注:D为下,R为右)

分析

这是一道普通的dp题,因为最小的零的个数就是5的最少个数和2的最少个数的最小值,所以我们进行两次dp分别求出2和5的数量然后取min。特别得,如果在路径中经过0则整个过程的0的总数就是1,所以在进行完两次dp后特判一下即可。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
int n,g[1100][1100],dp[1100][1100],now[1100][1100],best=1000000007;
string ans;
void work(int x,int y){
      if(x-1&&dp[x-1][y]+now[x][y]==dp[x][y]){
          work(x-1,y);
          ans.push_back('D');
      }else if(y-1){
          work(x,y-1);
          ans.push_back('R');
      }
}
void go(int wh){
      int i,j,k;
      memset(now,0,sizeof(now));
      for(i=1;i<=n;i++)
         for(j=1;j<=n;j++)
            while(g[i][j]&&g[i][j]%wh==0){
                now[i][j]++;
                g[i][j]/=wh;
            }
      memset(dp,0x3f,sizeof(dp));
      dp[1][1]=now[1][1];
      for(i=1;i<=n;i++)
         for(j=1;j<=n;j++){
             if(i-1)dp[i][j]=min(dp[i][j],dp[i-1][j]+now[i][j]);
             if(j-1)dp[i][j]=min(dp[i][j],dp[i][j-1]+now[i][j]);
         }
      if(dp[n][n]<best){
          ans="";
          best=dp[n][n];
          work(n,n);
      }
}
int main()
{     int i,j,k;
      scanf("%d",&n);
      for(i=1;i<=n;i++)
         for(j=1;j<=n;j++)
            scanf("%d",&g[i][j]);
      go(2);
      go(5);
      if(best>1){
        for(i=1;i<=n;i++)
           for(j=1;j<=n;j++)
              if(!g[i][j]){
                best=1;
                ans="";
                for(k=1;k<i;k++)ans.push_back('D');
                for(k=1;k<j;k++)ans.push_back('R');
                for(k=i;k<n;k++)ans.push_back('D');
                for(k=j;k<n;k++)ans.push_back('R');
                break;
              }
        }
      cout<<best<<endl<<ans<<endl;
      return 0;
}

转载于:https://www.cnblogs.com/yzxverygood/p/9025919.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值