Codeforces Beta Round #2_B. The least round way(DP)
来源:互联网 发布:淘宝网大童店铺 编辑:程序博客网 时间:2024/06/04 00:23
题目传送门:http://codeforces.com/contest/2/problem/B
题型:动态规划、数论
题意:
给出n*n的矩阵,从左上角走到右下角,只能向右走或者向下走,将路线上的值全部乘起来,问结果末尾0最少的路线。
分析:
乘积的末尾0,取决于这些数的质因子中的2和5的对数,即决定与最少的2的个数或者是最少的5的个数。若对矩阵中的每个元素进行质因子分解,复杂度为O(n^2*sqrt(n))过大。由于只要2的个数和5的个数,那么只要对每个元素不断除2或者除5即可,复杂度为O(n^2*log(n))可以接受。
采用DP进行路径的寻找,找出含2最少的路径和含5最少的路径,状态转移方程为:
dp(i,j) = min(dp(i-1,j),dp(i,j-1)) + num(i,j);
可以证明末尾0最少的路径是这两条路径中的一条,证明如下:
反证法:假设有一条路径比这两条更优。
所以这条路径的2和5的对数最少,所以相比与其他路径,该路径上必然2最少或者5最少。
然而根据题设,
这条路径含2的个数和含5的个数都不是最少的。
矛盾。
所以2最少的路或者5最少的路最优。 得证。
由于2最少的路径上的末尾0等于2的个数,5最少的路径上的末尾0等于5的个数,所以
ANS = min(dp2(n,n),dp5(n,n));
路径只需逆退即可。
需要注意的是,如果矩阵元素中有0且ANS>1,那么结果为1,路径就是经过该元素所在点的任意路径。
代码:
#include<iostream>#include<cmath>#include<cstring>#include<cstdio>#define INF 0x3f3f3f3fusing namespace std;int n;int num2[1010][1010];int num5[1010][1010];int dp2[1010][1010];int dp5[1010][1010];char str[1234];int _x,_y;void init(){memset(num2,0,sizeof(num2));memset(num5,0,sizeof(num5));for(int i=0;i<=n;i++){dp2[i][0] = dp2[0][i] = 0;dp5[i][0] = dp5[0][i] = 0;}}void FindRoute2(){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(i==1 && j==1){dp2[i][j] = num2[i][j];continue;}if(i==1){dp2[i][j] = dp2[i][j-1] + num2[i][j];continue;}if(j==1){dp2[i][j] = dp2[i-1][j] + num2[i][j];continue;}dp2[i][j] = min(dp2[i-1][j],dp2[i][j-1]) + num2[i][j];}}}void FindRoute5(){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(i==1 && j==1){dp5[i][j] = num5[i][j];continue;}if(i==1){dp5[i][j] = dp5[i][j-1] + num5[i][j];continue;}if(j==1){dp5[i][j] = dp5[i-1][j] + num5[i][j];continue;}dp5[i][j] = min(dp5[i-1][j],dp5[i][j-1]) + num5[i][j];continue;}}}void Ask2(){int pre = 0;int i=n,j=n;while(i!=1 || j!=1){if(dp2[i][j-1]<dp2[i-1][j]){str[pre] = 'R';j--;}else{str[pre] = 'D';i--;}pre++;}for(int i=pre-1;i>=0;i--){printf("%c",str[i]);}puts("");}void Ask5(){int pre = 0;int i=n,j=n;while(i!=1 || j!=1){if(dp5[i][j-1]<dp5[i-1][j]){str[pre] = 'R';j--;}else{str[pre] = 'D';i--;}pre++;}for(int i=pre-1;i>=0;i--){printf("%c",str[i]);}puts("");}void Special(int xx,int yy){for(int i=2;i<=xx;i++){printf("D");}for(int i=2;i<=n;i++){printf("R");}for(int i=xx+1;i<=n;i++){printf("D");}puts("");}int main(){while(~scanf("%d",&n)){bool ts = false;init();int a,tmp;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){scanf("%d",&a);if(a==0){_x = i;_y = j;ts = true;}tmp = a;while(tmp%2==0&&tmp>0){num2[i][j]++;tmp/=2;}tmp = a;while(tmp%5==0&&tmp>0){num5[i][j]++;tmp/=5;}}}FindRoute2();FindRoute5();int ans = min(dp2[n][n],dp5[n][n]);if(ts && ans>1){puts("1");Special(_x,_y);continue;}for(int i=0;i<=n;i++){dp2[i][0] = dp2[0][i] = INF;dp5[i][0] = dp5[0][i] = INF;}printf("%d\n",ans);if(dp2[n][n]<dp5[n][n]) Ask2();else Ask5();}return 0;}
- Codeforces Beta Round #2_B. The least round way(DP)
- Codeforces Beta Round #2B. The least round way
- Codeforces Beta Round #2 B. The least round way
- Codeforces Beta Round #2 B. The least round way dp,记录方案
- codeforces 2B The least round way DP因子路径
- Codeforces #2B The least round way(DP)
- codeforces 2B B. The least round way(dp+数论)
- CodeForces - 2B -The least round way (dp math)
- codeforces 2B The least round way
- codeforces 2B The least round way
- codeforces 2B The least round way
- Codeforces#2B The least round way
- [codeforces] 2B - The least round way
- Codeforces 2B The least round way
- 【Codeforces Beta Round 2B】【贪心 DP】The least round way 从(1,1)走到(n,n)乘积尾数0尽可能少
- CodeForces B. The least round way(dp)
- CodeForces 2BThe least round way(dp+数学)
- Codeforces #2B B. The least round way
- 【玩转微信公众平台之一】序章(纯粹扯淡)
- maven 项目 的构建
- 浅谈PHP中自动加载类库机制
- ARM基础知识(一)
- Python<11>函数基础
- Codeforces Beta Round #2_B. The least round way(DP)
- 二分查找
- 寻路包CAINav学习
- uva567 Risk(floyd)
- JSP note
- 数位dp小记
- CSS_样式sample
- 工资查询系统{给一贵族中学开发}
- hdu2553N皇后问题