题目链接:http://codeforces.com/contest/761/problem/C
题意:给定n个长度为m的字符串。每个字符串(字符串下标从0到m-1)都有一个指针,初始指针指向第0个位置。现在让你把每个字符串的指针移动到某个位置使得n个字符串中个个字符串的指针指向的字符组成一个新的密码串。并且这个密码串要合法。 一个合法的密码串一个满足:至少有一个数字,一个小写字母,一个给定的符号中的其中一个。问组成合法密码串的最小总移动步数。
思路:因为只有数字,字母,符号三个要求,并且密码串中都存在一个即可。所以先处理出n个字符串指针移动到这三种的最小步数。然后简单状压dp一下即可。 dp[i][j]表示目前处理到字符串i,状态为j时的最小移动步数(j只有三位分别对应三种要求,当某位为1时说明当前存在这种字符)
import java.io.PrintWriter; import java.util.*; public class Main { public static final int MAXN=50+5; public static final int MAXVAL=MAXN; public static String str[]=new String [MAXN]; public static int val[][]=new int [MAXN][3]; public static int dp[][]=new int [MAXN][(1<<3)]; public static int getVal(char s){ if(Character.isDigit(s)==true){ return 0; } if(Character.isLowerCase(s)==true){ return 1; } return 2; } public static void main(String[] args) { Scanner cin = new Scanner(System.in); PrintWriter out = new PrintWriter(System.out); int n=cin.nextInt(),m=cin.nextInt(); for(int i=1;i<=n;i++){ str[i]=cin.next(); Arrays.fill(val[i], MAXVAL); for(int j=0;j<m;j++){ int pos=getVal(str[i].charAt(j)); val[i][pos]=Math.min(val[i][pos],Math.min(j,m-j)); } } for(int i=0;i<=n;i++){ Arrays.fill(dp[i], MAXVAL*MAXVAL); } dp[0][0]=0; for(int i=1;i<=n;i++){ for(int j=0;j<(1<<3);j++){ dp[i][j]=dp[i-1][j]; } for(int j=0;j<(1<<3);j++){ for(int k=0;k<3;k++){ if(((j&(1<<k))==0)&&val[i][k]!=MAXVAL){ dp[i][(j|(1<<k))]=Math.min(dp[i][(j|(1<<k))], dp[i-1][j]+val[i][k]); } } } // for(int j=0;j<(1<<3);j++){ // out.printf("%d ", dp[i][j]); // } // out.println(); } out.println(dp[n][(1<<3)-1]); cin.close(); out.flush(); } }