挺好的题目,要做出来得有一定的数学功底(硬伤!!)。
题意:
给出一个矩阵 ,现在从左上角到右下角,求一条路径,这条路径上的各个点的乘积所得的数,这个数满足某位含有的0的个数最少。
题解:
状态:dp[i][j][2] 路径:dp[i][j][2]
题意:
给出一个矩阵 ,现在从左上角到右下角,求一条路径,这条路径上的各个点的乘积所得的数,这个数满足某位含有的0的个数最少。
题解:
状态:dp[i][j][2] 路径:dp[i][j][2]
0表示分解因子后含有2的个数,1表示含有5的个数。 会发现对应的2和5的最少个数(dp[i]j][0] dp[i][j][1])中哪个个数小取那个才会得到最优解。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
#define oo 0x3f3f3f3f
#define maxn 1000+50
int dp[maxn][maxn][2];
int path[maxn][maxn][2];
int main()
{
int n, x, f, r;
while (scanf("%d", &n) != EOF)
{
f = 0;
memset(dp, 0, sizeof dp);
memset(path, -1, sizeof path);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
{
scanf("%d", &x);
if (x == 0)
{
f = 1;
x = 10;
r = i;
}
while (x % 2 == 0)
{
dp[i][j][0]++;
x /= 2;
}
while (x % 5 == 0)
{
dp[i][j][1]++;
x /= 5;
}
}
for (int i = 2; i <= n; i++)
for (int k = 0; k <= 1; k++)
{
dp[1][i][k] += dp[1][i - 1][k];
dp[i][1][k] += dp[i - 1][1][k];
//0往下走 1往右走
path[1][i][k] = 1;
path[i][1][k] = 0;
}
for (int i = 2; i <= n; i++)
for (int j = 2; j <= n; j++)
for (int k = 0; k <= 1; k++)
{
if (dp[i - 1][j][k] < dp[i][j - 1][k])
{
dp[i][j][k] += dp[i - 1][j][k];
path[i][j][k] = 0;
}
else
{
dp[i][j][k] += dp[i][j - 1][k];
path[i][j][k] = 1;
}
}
int k = dp[n][n][1] < dp[n][n][0];
if (f && dp[n][n][k]>1)
{
printf("1\n");
for (int i = 2; i <= r; i++) printf("D");
for (int i = 2; i <= n; i++) printf("R");
for (int i = r + 1; i <= n; i++) printf("D");
}
else
{
printf("%d\n", dp[n][n][k]);
int i = n, j = n, len = 0;
char str[maxn << 1];
while (path[i][j][k] != -1)
{
str[++len] = path[i][j][k] == 0 ? 'D' : 'R';
if (path[i][j][k] == 0)
i--;
else
j--;
}
for (int i = len; i >= 1; i--)
printf("%c", str[i]);
puts("");
}
}
return 0;
}
/*
4
1 2 3 4
2 5 0 5
1 2 5 4
5 5 2 5
*/