codeforces 761 C. Dasha and Password(多维dp)
题目链接:http://codeforces.com/contest/761/problem/C
题意:给出n行的字符串每一列都从第一个元素开始可以左右移动每一行字符串都是首位相连的。
最后问最少移动几次能够构成一个合理字符串,构成方法每一行取当前位置那个数。只要这个字符串
中有数字,有小写字母,有特殊符号就算合理。
先预处理一下每行到达各种符号所要移动的最小距离,最后设p[i][j][k][l]
i=1表示有数字,0表示没有,j,k分别表示字母和特殊符号,l表示取到第l行。
最后p值表示最小要几步。
#include <iostream> #include <cstring> #define inf 0X3f3f3f3f using namespace std; int dp[60][4] , p[2][2][2][60]; char s[60][60]; int main() { int n , m; cin >> n >> m; for(int i = 0 ; i < n ; i++) { cin >> s[i]; } memset(dp , inf , sizeof(dp)); memset(p , inf , sizeof(p)); for(int i = 0 ; i < n ; i++) { for(int j = 0 ; j < m ; j++) { if(s[i][j] >= '0' && s[i][j] <= '9') { dp[i][1] = min(min(dp[i][1] , j) , m - j); } else if(s[i][j] >= 'a' && s[i][j] <= 'z') { dp[i][2] = min(min(dp[i][2] , j) , m - j); } else { dp[i][3] = min(min(dp[i][3] , j) , m - j); } } } for(int i = 0 ; i < n ; i++) { if(i == 0) { p[1][0][0][i] = dp[i][1]; p[0][1][0][i] = dp[i][2]; p[0][0][1][i] = dp[i][3]; } else { p[1][0][0][i] = min(p[1][0][0][i - 1] , dp[i][1]); p[1][1][0][i] = min(p[1][1][0][i - 1] , min(dp[i][1] + p[0][1][0][i - 1] , dp[i][2] + p[1][0][0][i - 1])); p[1][0][1][i] = min(p[1][0][1][i - 1] , min(dp[i][1] + p[0][0][1][i - 1] , dp[i][3] + p[1][0][0][i - 1])); p[1][1][1][i] = min(p[1][1][1][i - 1] , min(min(dp[i][1] + p[0][1][1][i - 1] , dp[i][2] + p[1][0][1][i - 1]) , dp[i][3] + p[1][1][0][i - 1])); p[0][1][0][i] = min(p[0][1][0][i - 1] , dp[i][2]); p[0][1][1][i] = min(p[0][1][1][i - 1] , min(dp[i][2] + p[0][0][1][i - 1] , dp[i][3] + p[0][1][0][i - 1])); p[0][0][1][i] = min(p[0][0][1][i - 1] , dp[i][3]); } } cout << p[1][1][1][n - 1] << endl; return 0; }