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][1]),如果ans=dp[i][j][0]就按path[i][j][0]输出,若ans=dp[i][j][1]也同理。
注意存在0的情况,若果路径中有一个0那么末尾0为1,若暗杀>1,则构造一条经过0的路径输出。

代码:

  1 #include<bits/stdc++.h>
  2 #define lc(a) (a<<1)
  3 #define rc(a) (a<<1|1)
  4 #define MID(a,b) ((a+b)>>1)
  5 #define fin(name)  freopen(name,"r",stdin)
  6 #define fout(name) freopen(name,"w",stdout)
  7 #define clr(arr,val) memset(arr,val,sizeof(arr))
  8 #define _for(i,start,end) for(int i=start;i<=end;i++)
  9 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
 10 using namespace std;
 11 typedef long long LL;
 12 const int N=1e3+5;
 13 const int INF=0x3f3f3f3f;
 14 const double eps=1e-10;
 15
 16 int n;
 17 int mp[N][N],dp[N][N][2],path[N][N][2];
 18
 19 struct node{
 20     int f,s;
 21     node(int f,int s):f(f),s(s){}
 22 };
 23
 24 bool judge(int x,int y){
 25     if(x>0&&x<=n&&y>0&&y<=n) return true;
 26     return false;
 27 }
 28
 29 void print(int x,int y,int type){
 30     if(path[x][y][type]==-1)
 31         return;
 32     if(path[x][y][type]==0)
 33         print(x-1,y,type);
 34     else
 35         print(x,y-1,type);
 36     printf("%c",path[x][y][type]==0?‘D‘:‘R‘);
 37 }
 38
 39 node cal(int x){
 40     int f=0,s=0;
 41     while(x){
 42         if(x%5==0){
 43             f++;
 44             x/=5;
 45         }
 46         else break;
 47     }
 48     while(x){
 49         if(x%2==0){
 50             s++;
 51             x/=2;
 52         }
 53         else break;
 54     }
 55     return node(f,s);
 56 }
 57
 58 int main(){
 59     scanf("%d",&n);
 60     int idx,idy;
 61     bool flag=false;
 62     memset(path,-1,sizeof(path));
 63     memset(dp,0x3f,sizeof(dp));
 64     for(int i=1;i<=n;i++){
 65         for(int j=1;j<=n;j++){
 66             scanf("%d",&mp[i][j]);
 67             if(mp[i][j]==0){
 68                 idx=i;
 69                 idy=j;
 70                 flag=true;
 71             }
 72         }
 73     }
 74     dp[1][1][0]=dp[1][1][1]=0;
 75     for(int i=1;i<=n;i++){
 76         for(int j=1;j<=n;j++){
 77             node t=cal(mp[i][j]);
 78             if(judge(i-1,j)){
 79                 dp[i][j][0]=dp[i-1][j][0];
 80                 dp[i][j][1]=dp[i-1][j][1];
 81                 path[i][j][1]=path[i][j][0]=0;
 82             }
 83             if(judge(i,j-1)){
 84                 if(dp[i][j][0]>dp[i][j-1][0]){
 85                     dp[i][j][0]=dp[i][j-1][0];
 86                     path[i][j][0]=1;
 87                 }
 88                 if(dp[i][j][1]>dp[i][j-1][1]){
 89                     dp[i][j][1]=dp[i][j-1][1];
 90                     path[i][j][1]=1;
 91                 }
 92             }
 93             dp[i][j][0]+=t.f;
 94             dp[i][j][1]+=t.s;
 95         }
 96     }
 97     int ans=min(dp[n][n][0],dp[n][n][1]);
 98     if(ans>1&&flag){
 99         puts("1");
100         for(int i=2;i<=idx;i++){
101             printf("D");
102         }
103         for(int j=2;j<=n;j++){
104             printf("R");
105         }
106         for(int i=idx+1;i<=n;i++){
107             printf("D");
108         }
109         return 0;
110     }
111     printf("%d\n",ans);
112     if(ans==dp[n][n][0])
113         print(n,n,0);
114     else
115         print(n,n,1);
116     return 0;
117 }

原文地址:https://www.cnblogs.com/fu3638/p/9104399.html

时间: 2024-10-31 10:06:31

Codeforces 2B The least round way(dp求最小末尾0)的相关文章

Codeforces #2B The least round way(DP)

Description 有一个n*n的正整数矩阵,要你求一条从第一行第一列的格子到第n行第n列的路,使得你走过的格子里面的数乘起来的值末尾的零的个数最小.输出最小个数. Input 第一行包含1个数n. 接下来n行每行n个数字. Output 一个数字表示末尾零最小个数. Sample Input 3 1 2 3 4 5 6 7 8 9 Sample Output 0 由于都是正数,对这个来说只需统计最少的2或5即可.相对简单. #include<cstdio> #include<cst

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; in

codeforces 2B The least round way

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 bott

CF 2B The least round way DP+Math

题意: 找出一条路, 使每个节点相乘,得到的数末尾 0 最少 每次移动只能向右或者向下, 找到后打印路径 ///按照题目要求,就是找出一条从左上角到右下角中每个数含2 or 5 最少的路 ///可以用Dp的思想, 然后把每个节点该走的方向记下来 ///再从终点回溯,把路径存入栈,再输出 ///数据会有0的情况, 这时候我们应该记录离终点最近的0 #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef

求n!末尾0的个数

n的阶乘后面有多少个0? 6的阶乘 = 1*2*3*4*5*6 = 720,720后面有1个0. Input一个数N(1 <= N <= 10^9)Output输出0的数量Sample Input 5 Sample Output 1 思路:有5作为乘数才能产生末尾0,求末尾有多少个0相当于求因子5的个数 n不断除以5 第一次除以5得到是1~n中因子含5的个数 第二次除以5得到的是1~n中因子含25的个数 ... 第n次除以5得到的是1~n中因子含5^n的个数代码: import java.ut

Codeforces 513C Second price auction 概率dp 求期望

题目链接:点击打开链接 题意: 有n个人去竞拍一件商品,下面给出n个区间表示每个人出的价是区间中随机的一个数(概率均等) 则第一名需要付的钱是第二名的竞拍价格(允许并列第一名) 求支付的钱的期望. 思路: 枚举付的钱,然后求付这个钱的概率,相乘后求和即可. 对于确定支付x元 分类讨论一下: 1.第一名出价大于x 枚举第一名,然后剩下来的人至少一个人出x元,其他人出<=x, P(剩下来的人一个人出x元,其他人出<=x) = P(剩下来的人出价<=x) - P(剩下的人出价<x) 2.

Codeforces 235B Let&#39;s Play Osu! (概率dp求期望+公式变形)

B. Let's Play Osu! time limit per test:2 seconds memory limit per test:256 megabytes You're playing a game called Osu! Here's a simplified version of it. There are n clicks in a game. For each click there are two outcomes: correct or bad. Let us deno

Codeforces 597C. Subsequences (树状数组+dp)

题目链接:http://codeforces.com/contest/597/problem/C 给你n和数(1~n各不同),问你长为k+1的上升自序列有多少. dp[i][j] 表示末尾数字为i 长度为j的上升子序列个数,但是dp数组是在树状数组的update函数中进行更新. update(i, val, j)函数表示在i的位置加上val,更新dp[i][j]. sum(i, j)就是求出末尾数字小于等于i 且长度为j的子序列有多少个. 1 //#pragma comment(linker,

CodeForces 540D Bad Luck Island 概率dp

CodeForces 540D 应该是简单概率dp,由于写得少显得十分蠢萌 求期望逆推,求概率正推,大概是这么个意思,贴一发留恋 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define db double const int maxn=108; db dp[maxn][maxn][maxn]; int main() { int i,j,n,m,k,p; whi