CodeForces B. The least round way(dp)

本文解析了CodeForces上的B题The least round way,详细介绍了如何通过动态规划找到矩阵中从左上角到右下角的一条路径,使得路径上数字乘积的末尾零的数量最少。代码实现考虑了特殊情况,如矩阵中存在零的情况。

转自:https://blog.youkuaiyun.com/u012860063/article/details/40517115

题目链接: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.youkuaiyun.com/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
*/

//添加说明(即为啥是ans=min(2的最小,5的最小)

1.当在2的个数最小的路径上,不会出现比单单在5的个数最小的路径下更小的了

2.同理当在5的个数最小的路径上,不会出现比单单在2的个数最小的路径下更小的了

源码来自:https://pan.quark.cn/s/41b9d28f0d6d 在信息技术领域中,jQuery作为一个广受欢迎的JavaScript框架,显著简化了诸多操作,包括对HTML文档的遍历、事件的管理、动画的设计以及Ajax通信等。 本篇文档将深入阐释如何运用jQuery达成一个图片自动播放的功能,这种效果常用于网站的轮播展示或幻灯片演示,有助于优化用户与页面的互动,使网页呈现更加动态的视觉体验。 为了有效实施这一功能,首先需掌握jQuery的核心操作。 通过$符号作为接口,jQuery能够迅速选取DOM组件,例如$("#id")用于选取具有特定ID的元素,而$(".class")则能选取所有应用了某类class的元素。 在选定元素之后,可以执行多种行为,诸如事件监听、样式的变更、内容的更新以及动画的制作等。 关于“一个基于jQuery的图片自动播放功能”,首要任务是准备一组图片素材,这些素材将被整合至一个容器元素之中。 例如,可以构建一个div元素,将其宽度设定为单张图片的尺寸,再借助CSS实现溢出内容的隐藏,从而构建出水平滚动的初始框架。 ```html<div id="slider"> <img src="image1.jpg" alt="Image 1"> <img src="image2.jpg" alt="Image 2"> <!-- 更多图片内容... --></div>```接着,需要编写jQuery脚本以实现图片的自动切换。 这通常涉及到定时器的运用,以设定周期性间隔自动更换当前显示的图片。 通过使用`.fadeOut()`和`.fadeIn()`方法,能够实现图片间的平滑过渡,增强视觉效果。 ```javascript$(document).re...
### Codeforces Div.2 比赛难度介绍 Codeforces Div.2 比赛主要面向的是具有基础编程技能到中级水平的选手。这类比赛通常吸引了大量来自全球不同背景的参赛者,包括大学生、高中生以及一些专业人士。 #### 参加资格 为了参加 Div.2 比赛,选手的评级应不超过 2099 分[^1]。这意味着该级别的竞赛适合那些已经掌握了一定算法知识并能熟练运用至少一种编程语言的人群参与挑战。 #### 题目设置 每场 Div.2 比赛一般会提供五至七道题目,在某些特殊情况下可能会更多或更少。这些题目按照预计解决难度递增排列: - **简单题(A, B 类型)**: 主要测试基本的数据结构操作和常见算法的应用能力;例如数组处理、字符串匹配等。 - **中等偏难题(C, D 类型)**: 开始涉及较为复杂的逻辑推理能力和特定领域内的高级技巧;比如图论中的最短路径计算或是动态规划入门应用实例。 - **高难度题(E及以上类型)**: 对于这些问题,则更加侧重考察深入理解复杂概念的能力,并能够灵活组合多种方法来解决问题;这往往需要较强的创造力与丰富的实践经验支持。 对于新手来说,建议先专注于理解和练习前几类较容易的问题,随着经验积累和技术提升再逐步尝试更高层次的任务。 ```cpp // 示例代码展示如何判断一个数是否为偶数 #include <iostream> using namespace std; bool is_even(int num){ return num % 2 == 0; } int main(){ int number = 4; // 测试数据 if(is_even(number)){ cout << "The given number is even."; }else{ cout << "The given number is odd."; } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值