题目链接 Dasha and Password
题目保证一定有解。
考虑到最多只有两行的指针需要移动,那么直接预处理出该行移动到字母数字或特殊符号的最小花费。
然后O(N^3)枚举求最小值即可。
时间复杂度O(N*M+N^3)
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define REP(i,n) for(int i(0); i < (n); ++i) 6 #define rep(i,a,b) for(int i(a); i <= (b); ++i) 7 #define dec(i,a,b) for(int i(a); i >= (b); --i) 8 #define for_edge(i,x) for(int i = H[x]; i; i = X[i]) 9 #define INF 1 << 30 10 11 const int N = 100000 + 10; 12 const int M = 10000 + 10; 13 const int Q = 100 + 10; 14 const int A = 30 + 1; 15 16 17 int a[Q][Q], c[Q][10], v[Q][10]; char s[Q]; 18 int n, m, ans; 19 20 int main(){ 21 22 scanf("%d%d", &n, &m); 23 rep(i, 1, n){ 24 scanf("%s", s + 1); 25 rep(j, 1, m){ 26 if (s[j] >= '0' && s[j] <= '9') a[i][j] = 1; 27 else if (s[j] >= 'a' && s[j] <= 'z') a[i][j] = 2; 28 else if (s[j] == '&' || s[j] == '*' || s[j] == '#') a[i][j] = 3; 29 } 30 } 31 32 rep(i, 1, n) rep(j, 1, 3) c[i][j] = INF; 33 34 rep(i, 1, n){ 35 rep(j, 1, m){ 36 v[i][a[i][j]] = 1; 37 c[i][a[i][j]] = min(c[i][a[i][j]], min(abs(j - 1), abs(m - j) + 1)); 38 } 39 } 40 41 42 ans = INF; 43 rep(i, 1, n - 2){ 44 rep(j, i + 1, n - 1){ 45 rep(k, j + 1, n){ 46 if (v[i][1] && v[j][2] && v[k][3]) ans = min(ans, c[i][1] + c[j][2] + c[k][3]); 47 if (v[i][1] && v[j][3] && v[k][2]) ans = min(ans, c[i][1] + c[j][3] + c[k][2]); 48 if (v[i][2] && v[j][1] && v[k][3]) ans = min(ans, c[i][2] + c[j][1] + c[k][3]); 49 if (v[i][2] && v[j][3] && v[k][1]) ans = min(ans, c[i][2] + c[j][3] + c[k][1]); 50 if (v[i][3] && v[j][1] && v[k][2]) ans = min(ans, c[i][3] + c[j][1] + c[k][2]); 51 if (v[i][3] && v[j][2] && v[k][1]) ans = min(ans, c[i][3] + c[j][2] + c[k][1]); 52 } 53 } 54 } 55 56 printf("%d ", ans); 57 return 0; 58 59 }