CF2B The least round way

https://www.luogu.com.cn/problem/CF2B

动态规划

\[f[i][j]表示从(1,1)走到(i,j)最少拥有的因子2数量\\ g[i][j]表示从(1,1)走到(i,j)最少拥有的因子5数量\\ 转移显然\\ 同时记录路径\\ 取ans=min(f[n][n],g[n][n]),特判有0的情况\\ 打印路径即可 \]

\(C++ Code:\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<stack>
#define N 1005
#define INF 123456789
using namespace std;
int dic[2][2]={{-1,0},{0,-1}};
char h[2]={'D','R'};
stack<char>s;
int n,x,sx,sy,two[N][N],five[N][N],f[N][N],g[N][N],ff[N][N][2],gg[N][N][2];
char cf[N][N],cg[N][N];
bool zero;
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        {
            scanf("%d",&x);
            if (!x)
            {
                sx=i;
                sy=j;
                zero=true;
            } else
            {
                while (x&&(x%2==0))
                {
                    two[i][j]++;
                    x/=2;
                }
                while (x&&(x%5==0))
                {
                    five[i][j]++;
                    x/=5;
                }
            }
        }
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            f[i][j]=g[i][j]=INF;
    f[1][1]=two[1][1],g[1][1]=five[1][1];
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            if (i==1&&j==1)
                continue; else
                {
                    for (int k=0;k<2;k++)
                    {
                        int nh=i+dic[k][0],nl=j+dic[k][1];
                        if (nh<1||nh>n||nl<1||nl>n)
                            continue;
                        if (f[nh][nl]+two[i][j]<f[i][j])
                        {
                            f[i][j]=f[nh][nl]+two[i][j];
                            ff[i][j][0]=nh,ff[i][j][1]=nl;
                            cf[i][j]=h[k];
                        }
                        if (g[nh][nl]+five[i][j]<g[i][j])
                        {
                            g[i][j]=g[nh][nl]+five[i][j];
                            gg[i][j][0]=nh,gg[i][j][1]=nl;
                            cg[i][j]=h[k];
                        }
                    }
                }
    int ans=min(f[n][n],g[n][n]);
    if (!zero||ans<=1)
    {
        printf("%d\n",ans);
        int i=n,j=n;
        while (i^1||j^1)
        {
            int Ri=i,Rj=j;
            if (f[n][n]<=g[n][n])
                s.push(cf[i][j]),i=ff[Ri][Rj][0],j=ff[Ri][Rj][1]; else
                s.push(cg[i][j]),i=gg[Ri][Rj][0],j=gg[Ri][Rj][1];   
        }
        while (!s.empty())
            putchar(s.top()),s.pop();
        putchar('\n');
    } else
    {
        puts("1");
        for (int i=1;i<sx;i++)
            putchar('D');
        for (int i=1;i<n;i++)
            putchar('R');
        for (int i=sx+1;i<=n;i++)
            putchar('D');
        putchar('\n');
    }
    return 0;
}
posted @ 2020-07-23 08:53  GK0328  阅读(97)  评论(0编辑  收藏  举报