https://cn.vjudge.net/problem/CodeForces-543C

题目

You have multiset of n strings of the same length, consisting of lowercase English letters. We will say that those strings are easy to remember if for each string there is some position i and some letter c of the English alphabet, such that this string is the only string in the multiset that has letter c in position i.

For example, a multiset of strings {"abc", "aba", "adc", "ada"} are not easy to remember. And multiset {"abc", "ada", "ssa"} is easy to remember because:

  • the first string is the only string that has character c in position 3;
  • the second string is the only string that has character d in position 2;
  • the third string is the only string that has character s in position 2.

You want to change your multiset a little so that it is easy to remember. For aij coins, you can change character in the j-th position of the i-th string into any other lowercase letter of the English alphabet. Find what is the minimum sum you should pay in order to make the multiset of strings easy to remember.

Input

The first line contains two integers n, m (1 ≤ n, m ≤ 20) — the number of strings in the multiset and the length of the strings respectively. Next n lines contain the strings of the multiset, consisting only of lowercase English letters, each string's length is m.

Next n lines contain m integers each, the i-th of them contains integers ai1, ai2, ..., aim (0 ≤ aij ≤ 106).

Output

Print a single number — the answer to the problem.

题解

把字符串一行一行地写出来

$n\leqslant 20$就暗示了可以二进制压位(压行)……

设$dp[k]$为容易记住的状态为k时的最小花费

有两种操作

  1. 改变记不住的行中的一个字符(n小于26,一定可以找到另外的字母),让这个字符串容易记
  2. 改变这一列中有与这个字符相同的字符的字符串,贪心保留最贵的位置,让这些字符串容易记

其中2是贪心多次1

但填表法可以按这种策略……

  1. 改变第一个记不住的行中的一个字符
  2. 改变第一个记不住的行中的一个字符的其他相同的行

反过来就是

  1. 从第一个行记不住的状态转移到现在的状态
  2. 从这些行记不住的转移到现在的状态

虽然其中2的这些行应该一次性记完,但一个字符串可以有多个独特的字符(算记多次),可能更省钱

  1. 5 2
  2. aa
  3. aa
  4. ab
  5. bb
  6. bb
  7. 1 100
  8. 100 100
  9. 1 1
  10. 100 100
  11. 100 1

修改为

  1. Ca
  2. aa
  3. DE
  4. bb
  5. bF

但是感觉还是有点牵强

(过了的代码)

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<cmath>
  5. #include<algorithm>
  6. #include<set>
  7. #include<iomanip>
  8. #include<queue>
  9.  
  10. #define REP(r,x,y) for(register int r=(x); r<(y); r++)
  11. #define REPE(r,x,y) for(register int r=(x); r<=(y); r++)
  12. #define PERE(r,x,y) for(register int r=(x); r>=(y); r--)
  13. #ifdef sahdsg
  14. #define DBG(...) printf(__VA_ARGS__)
  15. #else
  16. #define DBG(...) (void)0
  17. #endif
  18.  
  19. using namespace std;
  20. typedef long long LL;
  21. typedef pair<LL, LL> pll;
  22. typedef pair<int, int> pii;
  23.  
  24. template <class T>
  25. inline void read(T& x) {
  26. char c=getchar();
  27. int f=1;x=0;
  28. while(!isdigit(c)&&c!='-')c=getchar();
  29. if(c=='-')f=-1,c=getchar();
  30. while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=f;
  31. }
  32. template <class T,class... A>void read(T&t,A&...a){read(t);read(a...);}
  33.  
  34. char st[27][27];
  35. int c[27][27];
  36. int dp[1<<20];
  37. int ca[27][27],ka[27][27];
  38. inline int lg2(int x) {
  39. int k=0;
  40. while(x) x>>=1, k++;
  41. return k;
  42. }
  43. int main() {
  44. int n,m; read(n,m);
  45. REP(i,0,n) fgets(st[i],27,stdin);
  46. REP(i,0,n) REP(j,0,m) {
  47. read(c[i][j]);
  48. }
  49. memset(dp,0x3f,sizeof dp);
  50. REP(j,0,m) {
  51. REP(i,0,n) {
  52. ca[i][j]=0;
  53. int maxx=0;
  54. REP(k,0,n) if(st[i][j]==st[k][j]) {
  55. maxx=max(maxx,c[k][j]);
  56. ca[i][j]+=c[k][j];
  57. ka[i][j]|=1<<k;
  58. }
  59. ca[i][j]-=maxx;
  60. }
  61. }
  62. dp[0]=0;
  63. REP(k,0,1<<n) {
  64. int lb=(k)&(-k);
  65. int li=lg2(lb)-1;
  66. REP(j,0,m) {
  67. dp[k]=min(dp[k],dp[k^(k&ka[li][j])]+ca[li][j]);
  68. dp[k]=min(dp[k],dp[k^lb]+c[li][j]);
  69. }
  70. }
  71. printf("%d\n", dp[(1<<n)-1]);
  72. return 0;
  73. }

CF 543C Remembering Strings的更多相关文章

  1. Codeforces 543C Remembering Strings(DP)

    题意比较麻烦 见题目链接 Solution: 非常值得注意的一点是题目给出的范围只有20,而众所周知字母表里有26个字母.于是显然对一个字母进行变换后是不影响到其它字符串的. 20的范围恰好又是常见状 ...

  2. Codeforces Round #302 (Div. 1) C - Remembering Strings 状压dp

    C - Remembering Strings 思路:最关键的一点是字符的个数比串的个数多. 然后就能状压啦. #include<bits/stdc++.h> #define LL lon ...

  3. Codeforces Round #302 (Div. 1) C. Remembering Strings DP

    C. Remembering Strings Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/5 ...

  4. CF Set of Strings

    Set of Strings time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  5. CF Vitaly and Strings

    Vitaly and Strings time limit per test 1 second memory limit per test 256 megabytes input standard i ...

  6. Codeforces 544E Remembering Strings 状压dp

    题目链接 题意: 给定n个长度均为m的字符串 以下n行给出字符串 以下n*m的矩阵表示把相应的字母改动成其它字母的花费. 问: 对于一个字符串,若它是easy to remembering 当 它存在 ...

  7. codeforces 543 C Remembering Strings

    题意:若一个字符串集合里的每一个字符串都至少有一个字符满足在i位上,仅仅有它有,那么这个就是合法的,给出全部串的每一个字符修改的花费,求变成合法的最小代价. 做法:dp[i][j].前i个串的状态为j ...

  8. CF 149E Martian Strings 后缀自动机

    这里给出来一个后缀自动机的题解. 考虑对 $s$ 的正串和反串分别建后缀自动机. 对于正串的每个节点维护 $endpos$ 的最小值. 对于反串的每个节点维护 $endpos$ 的最大值. 这两个东西 ...

  9. CF543C Remembering Strings 状压dp

    Code: #include <cstdio> #include <algorithm> #include <cstring> #define setIO(s) f ...

随机推荐

  1. 【转载】解析 java 按值传递还是按引用传递

    原文链接  说明: (1):“在Java里面参数传递都是按值传递”这句话的意思是:按值传递是传递的值的拷贝,按引用传递其实传递的是引用的地址值,所以统称按值传递. (2):在Java里面只有基本类型和 ...

  2. 把list集合的内容写入到Xml中,通过XmlDocument方式写入Xml文件中

    List<Person> list = new List<Person> { new Person{Name="张三",Age=20,Email=" ...

  3. Java开发笔记(八十七)随机访问文件的读写

    前面介绍了字符流读写文件的两种方式,包括文件字符流和缓存字符流,但是它们的写操作都存在一个问题:不管是write方法还是append方法,都只能从文件开头写入,而不能追加到文件末尾或者在文件中间某个位 ...

  4. Java面试 32个核心必考点完全解析

    目录 课程预习 1.1 课程内容分为三个模块 1.2 换工作面临问题 1.3 课程特色 课时1:技术人职业发展路径 1.1 工程师发展路径 1.2 常见技术岗位划分 1.3 面试岗位选择 1.4 常见 ...

  5. 使用原生php爬取图片并保存到本地

    通过一个简单的例子复习一下几个php函数的用法 用到的函数或知识点 curl 发送网络请求 preg_match 正则匹配 代码 $url = 'http://desk.zol.com.cn/bizh ...

  6. Spring RestTemplate详解

    Spring RestTemplate详解   1.什么是REST? REST(RepresentationalState Transfer)是Roy Fielding 提出的一个描述互联系统架构风格 ...

  7. java自定义连接池

    1.java自定义连接池 1.1连接池的概念: 实际开发中"获取连接"或“释放资源”是非常消耗系统资源的两个过程,为了姐姐此类性能问题,通常情况我们采用连接池技术来贡献连接Conn ...

  8. Flutter项目之app升级方案

    题接上篇的文章的项目,还是那个空货管理app.本篇文章用于讲解基于Flutter的app项目的升级方案. 在我接触Flutter之前,做过一个比较失败的基于DCloud的HTML5+技术的app,做过 ...

  9. IntentService原理分析

    IntentService是一个异步处理请求的服务,通过Context#startService(Intent)可以将请求发送给IntentService,IntentService在工作线程中依次串 ...

  10. matplotlib正弦和余弦图

    代码: # -*- coding: utf-8 -*- """ Created on Thu Jul 12 16:37:47 2018 @author: zhen &qu ...