codeforces2b the least round way

给出一个矩阵,求从左上角到右下角找出一条路径,使得这条路径上的所有数的乘积后缀0最小。从左上角至右下角的输出路径。

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <math.h>
  5 #include <string.h>
  6 #include <algorithm>
  7 using namespace std;
  8 const int maxn=1005;
  9 int dp[maxn][maxn][4];
 10 int n,len;
 11 char s[2*maxn];
 12 /**
 13 解题思路:
 14 0的个数是有2*5来决定的.对于每个数,质因子分解出2,5的个数。
 15 找出2个数最小的路径l1上最后一个点的2的个数k
 16 找出5个数最小的路径l2上最后一个点的5的个数m
 17 对于l1来说,l2路径上最后一个点的2的个数会不小于k.
 18 对于l2来说,l1路径上最后一个点的5的个数会不小于m.
 19 所以要想使得后缀0最小,也就是min(k,m)最小的数就是解,
 20 对应路径输出即可。
 21 注意0的情况。
 22 0不存在 直接输出路径
 23 0存在,MIN>=1输出可行0路径
 24 0存在,MIN<1输出路径
 25 dp[i][j][0]从左上角到i,j点2的个数最小
 26 dp[i][j][1]从左上角到i,j点5的个数最小
 27 dp[i][j][2]到达2的方向
 28 dp[i][j][3]到达5的方向
 29 
 30 */
 31 void work(int k)
 32 {
 33     int x=n,y=n;
 34     while(x>=1&&y>=1)
 35     {
 36         s[len++]=dp[x][y][k];
 37         if(dp[x][y][k]=='D') x=x-1;
 38         else y=y-1;
 39         if(x==1&&y==1) break;
 40     }
 41 }
 42 int main()
 43 {
 44     int num,flag;
 45     while(scanf("%d",&n)!=EOF)
 46     {
 47         flag=0;
 48         memset(dp,0,sizeof(dp));
 49         for(int i=0; i<=n; i++)
 50         {
 51             dp[0][i][0]=dp[i][0][1]=dp[i][0][0]=dp[0][i][1]=99999999;
 52         }
 53         for(int i=1; i<=n; i++)
 54         {
 55             for(int j=1; j<=n; j++)
 56             {
 57                 scanf("%d",&num);
 58                 if(num==0) flag=i;
 59                     while(num&&num%2==0)
 60                     {
 61                         dp[i][j][0]++;
 62                         num/=2;
 63                     }
 64                 while(num&&num%5==0)
 65                 {
 66                     dp[i][j][1]++;
 67                     num/=5;
 68                 }
 69                 if(i==1&&j==1) continue;
 70                 if(i==1&&j>1)
 71                 {
 72                     dp[i][j][2]=dp[i][j][3]='R';
 73                     dp[i][j][0]+=dp[i][j-1][0];
 74                     dp[i][j][1]+=dp[i][j-1][1];
 75                     continue;
 76                 }
 77                 if(i>1&&j==1)
 78                 {
 79                     dp[i][j][2]=dp[i][j][3]='D';
 80                     dp[i][j][0]+=dp[i-1][j][0];
 81                     dp[i][j][1]+=dp[i-1][j][1];
 82                     continue;
 83                 }
 84                 if(dp[i][j-1][0]<dp[i-1][j][0])
 85                 {
 86                     dp[i][j][0]+=dp[i][j-1][0];
 87                     dp[i][j][2]='R';
 88                 }
 89                 else
 90                 {
 91                     dp[i][j][0]+=dp[i-1][j][0];
 92                     dp[i][j][2]='D';
 93                 }
 94                 if(dp[i][j-1][1]<dp[i-1][j][1])
 95                 {
 96                     dp[i][j][1]+=dp[i][j-1][1];
 97                     dp[i][j][3]='R';
 98                 }
 99                 else
100                 {
101                     dp[i][j][1]+=dp[i-1][j][1];
102                     dp[i][j][3]='D';
103                 }
104             }
105         }
106         int ans5=dp[n][n][1],ans2=dp[n][n][0];
107         len=0;
108         if(flag&&min(ans2,ans5)>=1)///没有考虑   存在0并且结果为0的情况
109         {
110             printf("1\n");
111             for(int i=1; i<flag; i++) printf("D");
112             for(int i=1; i<n; i++) printf("R");
113             for(int i=flag; i<n; i++) printf("D");
114             printf("\n");
115         }
116         else
117         {
118             if(ans2<ans5)
119             {
120                 printf("%d\n",dp[n][n][0]);
121                 work(2);
122             }
123             else
124             {
125                 printf("%d\n",dp[n][n][1]);
126                 work(3);
127             }
128             for(int i=len-1; i>=0; i--)
129                 printf("%c",s[i]);
130             printf("\n");
131         }
132     }
133     return 0;
134 }
View Code

 

转载于:https://www.cnblogs.com/linxhsy/p/4637137.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Codeforces Round 887是一个程序设计竞赛活动,由Codeforces组织举办。根据引用中的代码,该竞赛的题目要求解决一个序列操作的问题。给定一个长度为n的序列,通过执行一系列操作,使得序列变得非sorted,即非严格递增。具体操作是将序列中[1, i]范围内的数字全部加一,同时将[i+1, n]范围内的数字全部减一。问题要求求解最少需要执行多少次操作才能达到要求。 引用中的代码给出了解决这个问题的实现。代码首先读入序列的长度n和序列a。然后通过判断序列是否已经是非sorted,如果是则直接输出0。接下来,代码遍历序列,求出相邻两个数字的差的最小值。最后,计算出最少需要执行的操作次数,并输出结果。 需要注意的是,引用中的代码只是给出了解决问题的一种实现方式,并不代表Codeforces Round 887的具体题目和解答。要了解该竞赛的具体信息,需要参考Codeforces官方网站或相关资料。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Codeforces Round 887 (Div. 2)](https://blog.csdn.net/qq_36545889/article/details/131905067)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值