标签:最优 sync type air name printf pair mod lin
这题要特判矩阵里有0的情况,我就没特判,一直TLE(自己傻逼)
题意:给你一个矩阵,里面都是非负数,现在让你从\((1, 1)\)走到\((n, n)\), 并且把路径上的所有数乘起来,问你能得到的数末尾最少有多少个0。
思路:把路径上的每个数含有因子2和5的个数求出来(因为2和5才能凑出0),然后dp即可。注意特判有0的情况,如果矩阵有0,最后通常dp的答案\(>1\),那么经过0这个点能得到1这个最优解。
代码如下
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
#include<iomanip>
#define IOS cin.tie(0), ios::sync_with_stdio(false)
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1010, M = 1e5 + 10, mod = 1e9 + 7;
const double eps = 1e-12;
const double PI = acos(-1);
struct node{
int a, b;
char c;
};
pii f[N][N][2]; //一个是2的数目最少, 一个是5的数目最少
node pre[N][N][2];
vector<char> v;
int main()
{
int n, x;
scanf("%d", &n);
bool flag = false;
int p, q;
for(int i = 1 ; i <= n ; i ++)
for(int j = 1 ; j <= n ; j ++)
{
scanf("%d", &x);
if(x == 0) //特判有0的情况
{
flag = true;
p = i, q = j;
continue;
}
int a = 0, b = 0;
while(x % 10 == 0) x /= 10, a ++, b ++;
while(x % 2 == 0) x /= 2, a ++;
while(x % 5 == 0) x /= 5, b ++;
f[i][j][0] = f[i][j][1] = {a, b};
}
for(int i = 2 ; i <= n ; i ++)
{
f[i][1][0].x += f[i - 1][1][0].x;
f[i][1][0].y += f[i - 1][1][0].y;
pre[i][1][0] = {i - 1, 1, ‘D‘};
f[1][i][0].x += f[1][i - 1][0].x;
f[1][i][0].y += f[1][i - 1][0].y;
pre[1][i][0] = {1, i - 1, ‘R‘};
f[i][1][1].x += f[i - 1][1][1].x;
f[i][1][1].y += f[i - 1][1][1].y;
pre[i][1][1] = {i - 1, 1, ‘D‘};
f[1][i][1].x += f[1][i - 1][1].x;
f[1][i][1].y += f[1][i - 1][1].y;
pre[1][i][1] = {1, i - 1, ‘R‘};
}
for(int i = 2 ; i <= n ; i ++)
for(int j = 2 ; j <= n ; j ++)
{
if(f[i - 1][j][0].x < f[i][j - 1][0].x)
{
f[i][j][0].x += f[i - 1][j][0].x;
f[i][j][0].y += f[i - 1][j][0].y;
pre[i][j][0] = {i - 1, j, ‘D‘};
}
else
{
f[i][j][0].x += f[i][j - 1][0].x;
f[i][j][0].y += f[i][j - 1][0].y;
pre[i][j][0] = {i, j - 1, ‘R‘};
}
if(f[i - 1][j][1].y < f[i][j - 1][1].y)
{
f[i][j][1].x += f[i - 1][j][1].x;
f[i][j][1].y += f[i - 1][j][1].y;
pre[i][j][1] = {i - 1, j, ‘D‘};
}
else
{
f[i][j][1].x += f[i][j - 1][1].x;
f[i][j][1].y += f[i][j - 1][1].y;
pre[i][j][1] = {i, j - 1, ‘R‘};
}
}
int a = min(f[n][n][0].x, f[n][n][0].y), b = min(f[n][n][1].x, f[n][n][1].y);
int res = min(a, b);
if(flag && res > 1)
{
puts("1");
for(int i = 1 ; i < p ; i ++) putchar(‘D‘);
for(int j = 1 ; j < n ; j ++) putchar(‘R‘);
for(int i = p ; i < n ; i ++) putchar(‘D‘);
}
else
{
printf("%d\n", res);
if(a < b)
{
auto t = pre[n][n][0];
while(t.a != 0)
{
v.push_back(t.c);
t = pre[t.a][t.b][0];
}
}
else
{
auto t = pre[n][n][1];
while(t.a != 0)
{
v.push_back(t.c);
t = pre[t.a][t.b][1];
}
}
for(int i = v.size() - 1 ; i >= 0 ; i --) putchar(v[i]);
}
return 0;
}
标签:最优 sync type air name printf pair mod lin
原文地址:https://www.cnblogs.com/luoyicong/p/14612900.html