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的这些行应该一次性记完,但一个字符串可以有多个独特的字符(算记多次),可能更省钱

5 2
aa
aa
ab
bb
bb
1 100
100 100
1 1
100 100
100 1

修改为

Ca
aa
DE
bb
bF

但是感觉还是有点牵强

(过了的代码)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<iomanip>
#include<queue> #define REP(r,x,y) for(register int r=(x); r<(y); r++)
#define REPE(r,x,y) for(register int r=(x); r<=(y); r++)
#define PERE(r,x,y) for(register int r=(x); r>=(y); r--)
#ifdef sahdsg
#define DBG(...) printf(__VA_ARGS__)
#else
#define DBG(...) (void)0
#endif using namespace std;
typedef long long LL;
typedef pair<LL, LL> pll;
typedef pair<int, int> pii; template <class T>
inline void read(T& x) {
char c=getchar();
int f=1;x=0;
while(!isdigit(c)&&c!='-')c=getchar();
if(c=='-')f=-1,c=getchar();
while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=f;
}
template <class T,class... A>void read(T&t,A&...a){read(t);read(a...);} char st[27][27];
int c[27][27];
int dp[1<<20];
int ca[27][27],ka[27][27];
inline int lg2(int x) {
int k=0;
while(x) x>>=1, k++;
return k;
}
int main() {
int n,m; read(n,m);
REP(i,0,n) fgets(st[i],27,stdin);
REP(i,0,n) REP(j,0,m) {
read(c[i][j]);
}
memset(dp,0x3f,sizeof dp);
REP(j,0,m) {
REP(i,0,n) {
ca[i][j]=0;
int maxx=0;
REP(k,0,n) if(st[i][j]==st[k][j]) {
maxx=max(maxx,c[k][j]);
ca[i][j]+=c[k][j];
ka[i][j]|=1<<k;
}
ca[i][j]-=maxx;
}
}
dp[0]=0;
REP(k,0,1<<n) {
int lb=(k)&(-k);
int li=lg2(lb)-1;
REP(j,0,m) {
dp[k]=min(dp[k],dp[k^(k&ka[li][j])]+ca[li][j]);
dp[k]=min(dp[k],dp[k^lb]+c[li][j]);
}
}
printf("%d\n", dp[(1<<n)-1]);
return 0;
}

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. Python使用Ctypes与C/C++ DLL文件通信过程介绍及实例分析

    项目中可能会经常用到第三方库,主要是出于程序效率考虑和节约开发时间避免重复造轮子.无论第三方库开源与否,编程语言是否与当前项目一致,我们最终的目的是在当前编程环境中调用库中的方法并得到结果或者借助库中 ...

  2. DSAPI TreeView节点增删简化操作

    将一行或多行字符串添加到TreeView控件. 函数: 控件.TreeView控件.添加路径节点到TreeView(要添加节点的TreeView控件,字符串或字符串数组) 示例:将一个多行文本添加到T ...

  3. 【Oracle学习笔记】定时任务(dbms_job)

    一.概述 Oralce中的任务有2种:Job和Dbms_job,两者的区别有: 1.  jobs是oracle数据库的对象, dbms_jobs只是jobs对象的一个实例, 就像对于tables, e ...

  4. SAP HUM 事务代码HUMO为整托做Scrap

    SAP HUM 事务代码HUMO为整托做Scrap HUMO事务代码查询结果里,选择某个HU, 回车,过账成功, 2019-04-10 写于苏州市.  

  5. 基于mapnik做切片服务器的几点总结

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 在地图服务器的整体方案中,移动端采用矢量切片,样式解析采用th ...

  6. vmware完整克隆(linux)

    vmware中的完整克隆是基于指定的虚拟机克隆出相同的一份出来,不必再安装 但是我们要保证三个地方不能一样,一个是主机名称(hostname),一个是虚拟网卡设备mac地址,还有一个是ip地址 所以我 ...

  7. 无限极分类(adjacency list)的三种方式(迭代、递归、引用)

    一般的分类树状结构有两种方式: 一种是adjacency list,也就是是id,parent id这中形式. 另一种是nested set,即左右值的形式. 左右值形式查询起来比较高效,无需递归等, ...

  8. Android探究之View的绘制流程

    Android中Activity是作为应用程序的载体存在,代表着一个完整的用户界面,提供了一个窗口来绘制各种视图,当Activity启动时,我们会通过setContentView方法来设置一个内容视图 ...

  9. WebSocket-java实践

    websocket  主要用于  前端页面hmtl/jsp 与 后端进行socket得连接. 本例简单实现:一但后端接收到数据或者根据某些规则主动发送数据,那么可以根据不同用户等区别,发送给某个登陆得 ...

  10. C#隐式转换与显示转换

    System.Objec时C#中所有类型的基类,也就是万类之源. 一.值类型 值类型都继承自System.ValueType(派生自System.Objec),继承自System.ValueType的 ...