CodeForces B. The least round way(dp)

题目链接:http://codeforces.com/problemset/problem/2/B

B. The least round way

time limit per test

5 seconds

memory limit per test

64 megabytes

input

standard input

output

standard output

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.

Sample test(s)

input

3
1 2 3
4 5 6
7 8 9

output

0
DDRR

题意:

从左上到右下! 选出一条能让走过的路径的数字的积中含有最少的零!

PS:

积要含有零只能是2 或者5形成!寻找一条含有2或者5 最少的路径即可!

注意判断矩阵中是否有零的情况!

代码如下:

//http://blog.csdn.net/azheng51714/article/details/8240390
#include <cstdio>
#include <cstring>
const int maxn = 1017;
int m[2][maxn][maxn];
int dp[2][maxn][maxn];
//dp[0][i][j]到i、j时有多少个2;
//dp[1][i][j]到i、j时有多少个5;
int vis[2][maxn][maxn];
int n;

int solve(int mark)
{
    vis[mark][1][1] = 0;
    dp[mark][1][1] = m[mark][1][1];
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= n; j++)
        {
            if(i==1 && j==1)
                continue;
            if(i == 1)
            {
                dp[mark][i][j] = dp[mark][i][j-1] + m[mark][i][j];
                vis[mark][i][j] = 1;//向右
            }
            else if(j == 1)
            {
                dp[mark][i][j] = dp[mark][i-1][j] + m[mark][i][j];
                vis[mark][i][j] = 0;//向下
            }
            else
            {
                int tt1 = dp[mark][i-1][j];
                int tt2 = dp[mark][i][j-1];
                if(tt1 < tt2)
                {
                    dp[mark][i][j] = tt1 + m[mark][i][j];
                    vis[mark][i][j] = 0;
                }
                else
                {
                    dp[mark][i][j] = tt2 + m[mark][i][j];
                    vis[mark][i][j] = 1;
                }
            }
        }
    }
    return dp[mark][n][n];
}

void print(int mark, int x, int y)
{
    if(x==1 && y==1)
        return ;
    if(vis[mark][x][y] == 0)
    {
        print(mark,x-1,y);
        printf("D");
    }
    else
    {
        print(mark,x,y-1);
        printf("R");
    }
}

int main()
{
    int x, y;
    while(~scanf("%d",&n))
    {
        int tt, t1, t2;
        memset(vis,0,sizeof(vis));
        memset(m,0,sizeof(m));
        int flag = 0;
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= n; j++)
            {
                scanf("%d",&tt);
                if(tt == 0)
                {
                    flag = 1;
                    x = i;
                    y = j;
                    continue;
                }
                t1 = t2 = tt;
                while(t1%2 == 0)
                {
                    t1/=2;
                    m[0][i][j]++;
                }
                while(t2%5 == 0)
                {
                    t2/=5;
                    m[1][i][j]++;
                }
            }
        }

        int ans1 = solve(0);//路径存在最少的2的个数
        int ans2 = solve(1);//路径存在最少的5的个数
        //printf("ans1:%d ans2:%d\n",ans1,ans2);
        int mark = 0;
        int ans = 0;
        if(ans1 < ans2)
        {
            ans = ans1;
            mark = 0;
        }
        else
        {
            ans = ans2;
            mark = 1;
        }
        if(flag && ans > 1)
        {
            printf("1\n");//有零存在那么最终结果就只有一个零
            for(int i = 2; i <= x; i++)
            {
                //向下到有零的那一行
                printf("D");
            }
            for(int j = 2; j <= n; j++)
            {
                //走到最右边
                printf("R");
            }
            for(int i = x+1; i <= n; i++)
            {
                //走到最下边
                printf("D");
            }
            printf("\n");
            continue;
        }
        printf("%d\n",ans);
        print(mark, n, n);
        printf("\n");
    }
    return 0;
}

/*
3
4 10 5
10 9 4
6 5 3
3
4 10 5
6 0 2
7 8 9
*/
时间: 2024-12-15 04:28:57

CodeForces B. The least round way(dp)的相关文章

Codeforces 2B The least round way(dp求最小末尾0)

题目链接:http://codeforces.com/problemset/problem/2/B 题目大意: 给你一个nxn的矩形,找到一条从左上角到右下角的路径,使得该路径上所有数字的乘积的末尾0最少.解题思路:我们设k为2的因子数,m为5的因子数,那么一个数的末尾0的个数就是min(k,m).我们设dp[i][j][0]为从左上角到点(i,j)的乘积的最少2因子数,dp[i][j][1]为从左上角到点(i,j)的乘积的最少5因子数.那么ans=min(dp[i][j][0],dp[i][j

【Codeforces】CF 2 B The least round way(dp)

题目 传送门:QWQ 分析 求结尾0的数量QwQ. 10只能是$ 2 \times 5 $,我们预处理出每个数因子中2和5的数量. 我们接着dp出从左上到右下的经过的最少的2的数量和最少的5的数量.两者取min后就是答案. 特判数据中有0的情况,把他当做10处理.如果此时答案大于1,那么把答案更新成1.因为0只有1个0. 输出也有些小技巧 代码 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=1005; 4

codeforces 375B B. Maximum Submatrix 2(dp)

题目链接: codeforces 375B 题目大意: 给出一个01矩阵,行与行之间可以互换位置,问能够得到最大的全1矩阵的面积. 题目分析: 我们有一种模型,就是对于不互换行的01矩阵求最大面积,就是固定子矩阵的右下角,记录h[i][j]就是当前位置的高度,然后向左延展的距离,枚举所有的即可. 代码如下: #include <iostream> #include <cstring> #include <cstdio> #include <algorithm>

Codeforces Round #260 (Div. 1) A. Boredom (DP)

题目链接:http://codeforces.com/problemset/problem/455/A A. Boredom time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Alex doesn't like boredom. That's why whenever he gets bored, he comes up with

Codeforces118D Caesar&#39;s Legions(DP)

题目 Source http://codeforces.com/problemset/problem/118/D Description Gaius Julius Caesar, a famous general, loved to line up his soldiers. Overall the army had n1 footmen and n2 horsemen. Caesar thought that an arrangement is not beautiful if somewhe

【HDOJ 5653】 Bomber Man wants to bomb an Array.(DP)

[HDOJ 5653] Bomber Man wants to bomb an Array.(DP) Bomber Man wants to bomb an Array. Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 389    Accepted Submission(s): 117 Problem Description Give

【POJ 3071】 Football(DP)

[POJ 3071] Football(DP) Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4350   Accepted: 2222 Description Consider a single-elimination football tournament involving 2n teams, denoted 1, 2, -, 2n. In each round of the tournament, all tea

hdu 5623 KK&#39;s Number(dp)

问题描述 我们可爱的KK有一个有趣的数学游戏:这个游戏需要两个人,有N\left(1\leq N\leq 5*{10}^{4} \right)N(1≤N≤5∗10?4??)个数,每次KK都会先拿数.每次可以拿任意多个数,直到NN个数被拿完.每次获得的得分为取的数中的最小值,KK和对手的策略都是尽可能使得自己的得分减去对手的得分更大.在这样的情况下,最终KK的得分减去对手的得分会是多少? 输入描述 第一行一个数T\left( 1\leq T\leq 10\right)T(1≤T≤10),表示数据组

Ural 1353 Milliard Vasya&#39;s Function(DP)

题目地址:Ural 1353 定义dp[i][j],表示当前位数为i位时,各位数和为j的个数. 对于第i位数来说,总可以看成在前i-1位后面加上一个0~9,所以状态转移方程就很容易出来了: dp[i][j]=dp[i][j]+dp[i][j-1]+dp[i][j-2]+.......+dp[i][j-9]: 最后统计即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <