把过去和现在的笔记记录也搬了过来,也算是给以后留个念想吧,想想一开始打acm就是图一乐,后来发现这游戏还挺上头的,也算是度过了一段电竞生涯(xs)
早些时候的笔记写的好中二,连我自己看着都羞耻。
不过,就喜欢这种羞耻的感觉。
收录的题目大部分是个人认为质量不错的题目,以DP为主,非DP的题目都用※进行了标识。
当然,有些题解思路本身也是源自其他人的,不过除非特殊标注,否则都是用的自己的代码。

题目大意:

CF2B,the least round way
题目大意,给一个大小为N*N(1000)的矩阵,里面有一些数,求一条路径使得将路径上所有数乘起来得到的0数最少。

解:

一眼递推,非常简单,很容易发现每个2和5就能得到一个0,因此最后的0数量等于min(cnt5,cnt2),那么我只要记录两条路径,一条是2最少的,一条是5最少的,最后选择一条更加少的就可以了。
哦不,还有个特例:0可以把整条路径变成只有一个0。
还不能只特判0就结束了,毕竟有可能本来的路径可以一个0都没有。

绕来绕去还是那题,就是无缘无故感觉被耍了,烦躁,就当练习代码功底了。

代码

代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <utility>
#include <vector>
#include <istream>
#include <map>
#include <cmath>
#include <stack>
#include <set>
#include <cstring>
#include <string>
#define ll long long
#define maxn 500005
#define mdl 1000000007
#define clr(a,n) for(int i=0;i<n;i++)a[i]=0
#define cfast std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define pll pair<ll,ll>
#define pii pair<int,int>
#define inc(i,a,n) for(int i=a;i<n;i++)
#define vset(a,n,m) for(ll i=0;i<n;i++)a[i]=m;
#define endl '\n'
using namespace std;
int cnt2[1001][1001],dp2[1001][1001],dp5[1001][1001],cnt5[1001][1001];
pii rcd2[1001][1001],rcd5[1001][1001];
stack<char> ans;

int main() {
cfast;
int n;
scanf("%d", &n);
int pos0x=-1, pos0y=-1;
inc(i, 1, n + 1) {
inc(j, 1, n + 1) {
int d;
scanf("%d", &d);
if (d == 0)pos0x = i, pos0y = j;
int c2 = 0, c5 = 0;
while (d % 10 == 0&&d!=0) {
c2++;
c5++;
d /= 10;
}
while (d % 2 == 0&&d!=0) {
c2++;
d /= 2;
}
while (d % 5 == 0&&d!=0) {
c5++;
d /= 5;
}
cnt2[i][j] = c2;
cnt5[i][j] = c5;
// cout << c2 << " " << c5 << endl;
}
}

dp2[1][1] = cnt2[1][1];
dp5[1][1] = cnt5[1][1];
inc(i, 2, n + 1) {
dp2[i][1] = dp2[i - 1][1]+cnt2[i][1];
pii p;
p.first = i-1, p.second = 1;
rcd2[i][1] = p;
dp5[i][1] = dp5[i - 1][1]+cnt5[i][1];
p.first = i - 1, p.second = 1;
rcd5[i][1] = p;
}
inc(i, 2, n + 1) {
dp2[1][i] = dp2[1][i-1]+cnt2[1][i];
pii p;
p.first = 1, p.second =i- 1;
rcd2[1][i] = p;
dp5[1][i] = dp5[1][i-1]+cnt5[1][i];
p.first = 1, p.second = i-1;
rcd5[1][i] = p;
}
inc(i, 2, n + 1) {
inc(j, 2, n + 1) {
pii p;
p.first = i, p.second = j;
if (dp2[i - 1][j] < dp2[i][j - 1]) {
dp2[i][j] = dp2[i - 1][j] + cnt2[i][j];
p.first = i - 1,p.second=j;
rcd2[i][j] = p;
}
else {
dp2[i][j] = dp2[i][j-1] + cnt2[i][j];
p.first = i, p.second = j-1;
rcd2[i][j] = p;
}

if (dp5[i - 1][j] < dp5[i][j - 1]) {
dp5[i][j] = dp5[i - 1][j] + cnt5[i][j];
p.first = i - 1, p.second = j;
rcd5[i][j] = p;
}
else {
dp5[i][j] = dp5[i][j - 1] + cnt5[i][j];
p.first = i, p.second = j - 1;
rcd5[i][j] = p;
}
}
}
if (min(dp2[n][n], dp5[n][n]) > 0) {
if (pos0x != -1) {
printf("1\n");
for (int i = 1; i <= pos0x - 1; i++)printf("D");
for (int i = 1; i <= pos0y - 1; i++)printf("R");
for (int i = 1; i <= n - pos0x; i++)printf("D");
for (int i = 1; i <= n - pos0y; i++)printf("R");
return 0;
}
}
if (dp2[n][n] < dp5[n][n]) {
int x = n, y = n;
while (x * y != 1) {
pii p = rcd2[x][y];
if (p.first == x - 1)ans.push('D');
else ans.push('R');
x = p.first, y = p.second;
}
printf("%d\n", dp2[n][n]);
while (ans.size()) {
printf("%c", ans.top());
ans.pop();
}
}
else {
int x = n, y = n;
while (x * y !=1) {
pii p = rcd5[x][y];
if (p.first == x - 1)ans.push('D');
else ans.push('R');
x = p.first, y = p.second;
}
printf("%d\n", dp5[n][n]);
while (ans.size()) {
printf("%c", ans.top());
ans.pop();
}
}
}


/*
3
2 2 2
5 5 5
5 5 5
*/