The least round way

https://www.luogu.org/problemnew/show/CF2B

题意翻译

题目描述

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

以左上角为起点

每次只能向右或向下走

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

输入格式

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

输出格式

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

emmm洛谷上虽然是蓝题但感觉蛮水的。但是写了好长!

先将每个数字分解,存这个数字质因数2和5的个数。然后dp,找到dp[n-1][n-1]中min(2,5)。然后有一点需要注意的是存在有0的数据,那么只要特判一下,有没有min(2,5)==0的,有就输出这条路径,没有就输出穿过0的路径。

对于路径输出,拿一个数组在dp的时候存一下,判断是从上还是从左走来的,输出的时候用递归逆向寻路。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<stack>
#include<string>
#include<algorithm>
#include<cmath>
#define rg register
#define il inline
#define Bin(a) (1<<(a))
#include<bitset>
#define INF 0x7fffffff
using namespace std;
typedef unsigned long long ll;
const int maxn=1005;
int dp[maxn][maxn][2];
int pre[maxn][maxn][3];
int fa[maxn][maxn][2];
int n,indexx=INF;
int read(){
    int ans=0,flag=1;char ch;
    while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1;
    ans=ch^48;
    while((ch=getchar())>='0'&&ch<='9') ans=(ans<<3)+(ans<<1)+(ch^48);
    return flag*ans;
}
void init(){
    for(rg int i=0;i<n;i++){
        for(rg int j=0;j<n;j++){
            pre[i][j][0]=read();
            if(pre[i][j][0]==0){
                indexx=j;
                continue;
            }
            while(pre[i][j][0]%2==0){
                pre[i][j][1]++;
                pre[i][j][0]/=2;
            }
            while(pre[i][j][0]%5==0){
                pre[i][j][2]++;
                pre[i][j][0]/=5;
            }
        }
    }
}
void print(int y,int x,int shit){
    if(x==0&&y==0) return ;
    //printf("%d %d\n",x,y);
    if(fa[y][x][shit]==0){
        print(y,x-1,shit);
        putchar('R');
    }
    else{
        print(y-1,x,shit);
        putchar('D');
    }
}
int main(){
    n=read();
    init();
    dp[0][0][0]=pre[0][0][1];
    dp[0][0][1]=pre[0][0][2];
    for(rg int i=0;i<n;i++){
        for(rg int j=0;j<n;j++){
            if(j&&i){
                if(dp[i][j-1][0]<dp[i-1][j][0]){
                    dp[i][j][0]=dp[i][j-1][0]+pre[i][j][1];
                    fa[i][j][0]=0;
                }
                else{
                    dp[i][j][0]=dp[i-1][j][0]+pre[i][j][1];
                    fa[i][j][0]=1;
                }
                if(dp[i][j-1][1]<dp[i-1][j][1]){
                    dp[i][j][1]=dp[i][j-1][1]+pre[i][j][2];
                    fa[i][j][1]=0;
                }
                else{
                    dp[i][j][1]=dp[i-1][j][1]+pre[i][j][2];
                    fa[i][j][1]=1;
                }
            }
            else if(j){
                dp[i][j][0]=dp[i][j-1][0]+pre[i][j][1];
                fa[i][j][0]=0;
                dp[i][j][1]=dp[i][j-1][1]+pre[i][j][2];
                fa[i][j][1]=0;
            }
            else if(i){
                dp[i][j][0]=dp[i-1][j][0]+pre[i][j][1];
                fa[i][j][0]=1;
                dp[i][j][1]=dp[i-1][j][1]+pre[i][j][2];
                fa[i][j][1]=1;
            }
        }
    }
    int shit=dp[n-1][n-1][0]>dp[n-1][n-1][1]?1:0;
    if(dp[n-1][n-1][shit]>=1&&indexx!=INF){
        puts("1");
        for(rg int i=0;i<indexx;i++)
            putchar('R');
        for(rg int i=1;i<n;i++)
            putchar('D');
        for(rg int i=indexx+1;i<n;i++)
            putchar('R');
        return 0;
    }
    printf("%d\n",dp[n-1][n-1][shit]);
    print(n-1,n-1,shit);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ffscas/article/details/86708824
way