codeforces 2B The least round way 【DP】

VJ上可找到中文题意。

思路:

首先分解有多少2与多少5.接下来就是dp。

分两次,一次是根据2的数量贪心,另外一次是根据5的数量贪心,看哪一次乘积的末尾0最少。

需要注意的是两点:

1.输入有0的情况,要判断你的ans是不是大于1如果大于1那么输出一条经过0的路径即可。

2.当根据2的数量贪心进行dp的时候,如果可以转移的两个来源的2的数量是相同的,需要找到5的数量较小的状态转移过来。

代码较挫。

#include<bits/stdc++.h>
using namespace std;
int er[1005][1005],wu[1005][1005];
int dp[1005][1005],dpp[1005][1005];
bool from1[1005][1005],from2[1005][1005];
void print(bool p[][1005],int n){
    stack<int>s;
    int x=n-1,y=n-1;
    while(x!=0||y!=0){
        s.push(p[x][y]);
        if(p[x][y]==0)y--;
        else x--;
    }
    while(!s.empty()){
        int tmp=s.top();
        s.pop();
        if(tmp)printf("D");
        else printf("R");
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    bool ok=0;
    int x,y;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            int tmp;
            scanf("%d",&tmp);
            if(tmp==0){
                ok=1;
                x=i;y=j;
                continue;
            }
            while(tmp%2==0){
                tmp/=2;
                er[i][j]++;
            }
            while(tmp%5==0){
                tmp/=5;
                wu[i][j]++;
            }
        }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(i==0){
                if(j!=0){
                    dp[i][j]=dp[i][j-1]+er[i][j];
                    dpp[i][j]=dpp[i][j-1]+wu[i][j];
                    from1[i][j]=0;
                }
                else{
                    dp[i][j]=er[i][j];
                    dpp[i][j]=wu[i][j];
                }
            }
            else{
                if(j!=0){
                    if(dp[i-1][j]<dp[i][j-1]){
                        dp[i][j]=dp[i-1][j]+er[i][j];
                        dpp[i][j]=dpp[i-1][j]+wu[i][j];
                        from1[i][j]=1;
                    }
                    else if(dp[i-1][j]==dp[i][j-1]){
                        if(dpp[i-1][j]<dpp[i][j-1]){
                            dp[i][j]=dp[i-1][j]+er[i][j];
                            dpp[i][j]=dpp[i-1][j]+wu[i][j];
                            from1[i][j]=1;
                        }
                        else{
                            dp[i][j]=dp[i][j-1]+er[i][j];
                            dpp[i][j]=dpp[i][j-1]+wu[i][j];
                            from1[i][j]=0;
                        }
                    }
                    else{
                        dp[i][j]=dp[i][j-1]+er[i][j];
                        dpp[i][j]=dpp[i][j-1]+wu[i][j];
                        from1[i][j]=0;
                    }
                }
                else{
                    dp[i][j]=dp[i-1][j]+er[i][j];
                    dpp[i][j]=dpp[i-1][j]+wu[i][j];
                    from1[i][j]=1;
                }
            }
        }
    }
    int ans=min(dp[n-1][n-1],dpp[n-1][n-1]);
    memset(dp,0,sizeof(dp));
    memset(dpp,0,sizeof(dpp));
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(i==0){
                if(j!=0){
                    dp[i][j]=dp[i][j-1]+wu[i][j];
                    dpp[i][j]=dpp[i][j-1]+er[i][j];
                    from2[i][j]=0;
                }
                else{
                    dp[i][j]=wu[i][j];
                    dpp[i][j]=er[i][j];
                }
            }
            else{
                if(j!=0){
                    if(dp[i-1][j]<dp[i][j-1]){
                        dp[i][j]=dp[i-1][j]+wu[i][j];
                        dpp[i][j]=dpp[i-1][j]+er[i][j];
                        from2[i][j]=1;
                    }
                    else if(dp[i-1][j]==dp[i][j-1]){
                        if(dpp[i-1][j]<dpp[i][j-1]){
                            dp[i][j]=dp[i-1][j]+wu[i][j];
                            dpp[i][j]=dpp[i-1][j]+er[i][j];
                            from2[i][j]=1;
                        }
                        else{
                            dp[i][j]=dp[i][j-1]+wu[i][j];
                            dpp[i][j]=dpp[i][j-1]+er[i][j];
                            from2[i][j]=0;
                        }
                    }
                    else{
                        dp[i][j]=dp[i][j-1]+wu[i][j];
                        dpp[i][j]=dpp[i][j-1]+er[i][j];
                        from2[i][j]=0;
                    }
                }
                else{
                    dp[i][j]=dp[i-1][j]+wu[i][j];
                    dpp[i][j]=dpp[i-1][j]+er[i][j];
                    from2[i][j]=1;
                }
            }
        }
    }
    if(ans>min(dp[n-1][n-1],dpp[n-1][n-1])){
        ans=min(dp[n-1][n-1],dpp[n-1][n-1]);
        if(ans>1&&ok){
            puts("1");
            for(int i=0;i<x;i++){
                printf("D");
            }
            for(int j=0;j<n-1;j++){
                printf("R");
            }
            for(int i=x;i<n-1;i++){
                printf("D");
            }
            return 0;
        }
        printf("%d\n",min(dp[n-1][n-1],dpp[n-1][n-1]));
        print(from2,n);
    }
    else{
        if(ans>1&&ok){
            puts("1");
            for(int i=0;i<x;i++){
                printf("D");
            }
            for(int j=0;j<n-1;j++){
                printf("R");
            }
            for(int i=x;i<n-1;i++){
                printf("D");
            }
            return 0;
        }
        printf("%d\n",ans);
        print(from1,n);
    }
}
时间: 2024-10-28 22:47:07

codeforces 2B 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 - 1067A Array Without Local Maximums【dp】

学习博客:戳这里 附本人代码: 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e5 + 10; 5 const ll mod = 998244353; 6 set<int>nu[maxn], rol[2]; 7 int a[maxn]; 8 ll dp[maxn][222][3]; 9 int main() { 10 int n; 11 sc

Codeforces 447 C DZY Loves Sequences【DP】

题意:给出一列数,在这个序列里面找到一个连续的严格上升的子串,现在可以任意修改序列里面的一个数,问得到的子串最长是多少 看的题解,自己没有想出来 假设修改的是a[i],那么有三种情况, 1.a[i]>a[i-1],那么求出向左能够延伸的最长的长度 2.a[i]<a[i-1],那么求出向右能够延伸的最长的长度 3.如果修改的这个数刚好夹在两个数的中间,这种情况比上面两种都优, 即为a[i-1]<a[i+1]-1,求出左右能够延伸的最长的长度 然后因为a[i]本身还没有算进去,所以求出最大值

hdoj 2391 Filthy Rich 【DP】

题目大意:有个二维数组,你从(0,0)出发,最终到(n,m), 在这个二维数组中,每个位置dp[i][j]都有一定量的黄金,你可以拾取,问你最多能失去多少,并且,你的方向有下,右, 斜向下三个方向: 策略:就是每一个都加上它的上方向与左方向的最大值,这样到最后就是最大值.详情见代码 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2391 代码: #include<stdio.h> #include<string.h> int dp[1

HDOJ1176 免费馅饼 【DP】+【经典数塔】

免费馅饼 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 23986    Accepted Submission(s): 8093 Problem Description 都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼.说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的1

nyoj 325 zb的生日 【DP】||【DFS】

两种方法: 第一种:将总数一半当做背包,用总数-2*最多能装的数目就是所求: 第二种:深搜: zb的生日 时间限制:3000 ms  |  内存限制:65535 KB 难度:2 描述 今天是阴历七月初五,acm队员zb的生日.zb正在和C小加.never在武汉集训.他想给这两位兄弟买点什么庆祝生日,经过调查,zb发现C小加和never都很喜欢吃西瓜,而且一吃就是一堆的那种,zb立刻下定决心买了一堆西瓜.当他准备把西瓜送给C小加和never的时候,遇到了一个难题,never和C小加不在一块住,只能

HDOJ4540 威威猫系列故事——打地鼠 【DP】

威威猫系列故事--打地鼠 Time Limit: 300/100 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 1445    Accepted Submission(s): 713 Problem Description 威威猫最近不务正业,每天沉迷于游戏"打地鼠". 每当朋友们劝他别太着迷游戏,应该好好工作的时候,他总是说,我是威威猫,猫打老鼠就是我的工作! 无话

NYOJ16 矩形嵌套 【DP】

矩形嵌套 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度).例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中.你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内. 输入 第一行是一个正正数N(0<N<10),表示测试数据组数, 每组

hdoj 2046 骨牌铺方格 【DP】+【斐波那契】

dp果然不是好学的... 第n个,即2*n时,可由第n-1个的竖直排列再加一个,和第n-2个中横着排两个 所以f(n) = 1×f(n-1) + 1×f(n-2): 骨牌铺方格 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 28412    Accepted Submission(s): 13771 Problem Descripti