链接:http://codeforces.com/problemset/problem/2/B
题意:在一个棋盘上从左上角走到右下角,求经过点的乘积的结果尾数的0最少,要输出路径
题解:记录每个格子2和5的因子数,做两次dp,取较小的那个。有0的情况要特殊判断,可以把0当作10,最后的结果如果大于1,那么按照经过0来处理。记录路径记录前驱即可。但是不知道test 31为何wa了。。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<stack>
using namespace std;
int n, a[1002][1002];
int num[1002][1002][2]; //0表示2因子个数,1表示5因子个数
int dp[1002][1002][2];
int path[1002][1002][2];
int mov[1002*1002];
int zx = -1, zy = -1;
void output(int k){
/*if(i == 1 && j == 1){
return;
}
if(path[i][j][k] == 1){
output(i-1, j, k);
printf("D");
}
else{
output(i, j-1, k);
printf("R");
}*/
int cnt = 0;
int i = n, j = n;
while(i!=1 || j!=1){
if(path[i][j][k] == 1){
mov[cnt++] = 1;
i = i-1;
}
else{
mov[cnt++] = 0;
j = j-1;
}
}
for(int i = cnt-1; i>=0; i--){
if(mov[i] == 1) printf("D");
else printf("R");
}
printf("\n");
}
int main(){
scanf("%d", &n);
for(int i = 1; i<=n; i++){
for(int j = 1; j<=n; j++){
scanf("%d", &a[i][j]);
}
}
for(int i = 1; i<=n; i++){
for(int j = 1; j<=n; j++){
int temp = a[i][j];
if(a[i][j] == 0){
temp = 10;
zx = i; zy = j;
}
while(temp%2 == 0){
num[i][j][0]++;
temp/=2;
}
while(temp%5 == 0){
num[i][j][1]++;
temp/=5;
}
}
}
/*for(int i = 1; i<=n; i++){
for(int j = 1; j<=n; j++){
cout<<num[i][j][0]<<"-"<<num[i][j][1]<<" ";
}
cout<<endl;
}*/
for(int i = 1; i<=n; i++){
dp[1][i][0] = dp[1][i-1][0]+num[1][i][0];
path[1][i][0] = 0;
dp[i][1][0] = dp[i-1][1][0]+num[i][1][0];
path[i][1][0] = 1;
dp[1][i][1] = dp[1][i-1][1]+num[1][i][1];
path[1][i][1] = 0;
dp[i][1][1] = dp[i-1][1][1]+num[i][1][1];
path[i][1][1] = 1;
}
for(int i = 2; i<=n; i++){
for(int j = 2; j<=n; j++){
dp[i][j][0] = min(dp[i-1][j][0], dp[i][j-1][0])+num[i][j][0];
path[i][j][0] = dp[i-1][j][0]>dp[i][j-1][0]?0:1;
dp[i][j][1] = min(dp[i-1][j][1], dp[i][j-1][1])+num[i][j][1];
path[i][j][1] = dp[i-1][j][1]>dp[i][j-1][1]?0:1;
}
}
int res;
res = min(dp[n][n][0], dp[n][n][1]);
int k = dp[n][n][0]>dp[n][n][1]?1:0;
/*for(int i = 1; i<=n; i++){
for(int j = 1; j<=n; j++){
cout<<path[i][j][1]<<" ";
}
cout<<endl;
}
cout<<endl;
for(int i = 1; i<=n; i++){
for(int j = 1; j<=n; j++){
cout<<dp[i][j][1]<<" ";
}
cout<<endl;
}*/
if(zx!=-1){
printf("1\n");
for(int i = 1; i<zx; i++){
printf("D");
}
for(int i = 1; i<=n; i++){
printf("R");
}
for(int i = zx; i<n; i++){
printf("D");
}
printf("\n");
}
else{
printf("%d\n", res);
output(k);
}
//cout<<dp[2][3][0]<<" "<<dp[3][3][1]<<endl;
return 0;
}