纪念下如此2B的题号。。。
DP啊,神啊,我看见DP俩字就颤 = =
第一反应是把每个数都分解为几个2几个5,以前ZOJ有道水题是计算多少个数乘积后有几个零,就是那种做法。
然后想着DP下最小的2或者5,想着不对,因为前面的2或者5的选择会影响后面,结果纠结了。
CFY说了个做法,扫两遍,单独计算2,5,然后目标点取最小的那个值即可。。。大悟。。T T 。。
找路径的话,就相当于从目标点往回找啦,或者你计算2,5的时候顺带记录下路径也可以。
关于0的处理,我是把0当做1个2, 1个5处理了,如果这个结果大于1,那么就输出1哈,因为有0的话,无论乘多少都是0。
改变代码风格了,发现木有哈~向C++靠拢。。
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <climits>
#include <cstring>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define FOR(i,s,t) for(int i=(s); i<(t); i++)
#define BUG puts("here!!!")
#define STOP system("pause")
#define file_r(x) freopen(x, "r", stdin)
#define file_w(x) freopen(x, "w", stdout)
using namespace std;
const int MAX = 1010;
class NODE{
public:
int num[2];
void add(int n2, int n5){
this->num[0] = n2;
this->num[1] = n5;
}
void init(int v){
if( v == 0 )
add(1, 1);
else
factor(v);
}
int ff(int v, int base){
int ans = 0;
while( v % base == 0 && v ){
ans++;
v /= base;
}
return ans;
}
void factor(int v){
add(ff(v, 2), ff(v, 5));
}
};
NODE node[MAX][MAX];
int a2[MAX][MAX];
int a5[MAX][MAX];
void process(int n, int a[][MAX], int id){
a[0][0] = node[0][0].num[id];
FOR(i, 1, n)
a[i][0] = a[i-1][0] + node[i][0].num[id];
FOR(i, 1, n)
a[0][i] = a[0][i-1] + node[0][i].num[id];
FOR(i, 1, n)
FOR(k, 1, n){
a[i][k] = min(a[i-1][k], a[i][k-1]) + node[i][k].num[id];
}
}
int dp(int n){
memset(a2, 0, sizeof(a2));
memset(a5, 0, sizeof(a5));
process(n, a2, 0);
process(n, a5, 1);
return min(a2[n-1][n-1], a5[n-1][n-1]);
}
string road(int n, int a[][MAX], int val, int id){
string out;
int x = n-1, y = n-1;
while( x != 0 || y != 0 ){
if( x != 0 && a[x][y] == a[x-1][y] + node[x][y].num[id] ){
x--;
out += 'D';
} else {
if( y != 0 && a[x][y] == a[x][y-1] + node[x][y].num[id] ){
y--;
out += 'R';
}
}
}
string ans;
for(int i=out.length()-1; i>=0; i--){
ans += out[i];
}
return ans;
}
int main()
{
int n, value;
bool zero = false;
int x, y;
scanf("%d", &n);
FOR(i, 0, n)
FOR(k, 0, n){
scanf("%d", &value);
if( !value ){
zero = true;
x = i;
y = k;
}
node[i][k].init(value);
}
int ans = dp(n);
if( zero && ans >= 1 ){
puts("1");
FOR(i, 0, x)
putchar('D');
FOR(i, 0, y)
putchar('R');
FOR(i, x+1, n)
putchar('D');
FOR(i, y+1, n)
putchar('R');
} else {
string out;
if( ans == a2[n-1][n-1] )
out = road(n, a2, ans, 0);
else
out = road(n, a5, ans, 1);
printf("%d\n%s\n", ans, out.c_str());
}
return 0;
}