• Codeforces Round #394 (Div. 2)


    题目链接: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();
        }
    }
  • 相关阅读:
    C加加学习之路 1——开始
    哈夫曼树C++实现详解
    Linux常用命令
    Accp第二章:基础知识
    第一章Accp 8.0
    泛型集合
    深入C#数据类型
    初始wondows系统
    深入.NET框架
    二至十五章总结
  • 原文地址:https://www.cnblogs.com/kirito520/p/6420281.html
Copyright © 2020-2023  润新知