E. Remembering Strings

题目大意

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.

数据范围

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).


题解

被$Lijinnn$讲得贼神,看题解感觉还好。

首先我们需要发现,每一列的每一种字符只可能有两种改动情况。

第一种是把一行的一个字符改掉。

第二种是把这列中的某个字符全都改掉然后留下一个权值最大的。

这是显然的吧....不一定是唯一的但一定是最优的。

接下来就是$dp$了,假设$f[S]$表示状态为$S$的字符串合法了,考虑每列每行都有一种转移方式,暴力转移更新即可。

其实还有一个小优化,但是仗着$CF$评测机快没必要。

是这样的,就是我们发现,先更改某行某列,再更改另一行另一列,和把他们的顺序调换回来是一样的。

所以,我们在用$S$向后转移的时候,只需要任取一个$0$位往后转移即可。

不能保证中间的每一个$f[S]$都是最优的,但是能保证$f[(1<<n)-1]$是最优的,以及更新到最终答案的那一条链是最优的。

代码:(这个小优化就体现在,判断$0$的那个$if$中的那个$break$)

#include <bits/stdc++.h>

#define N 21 

using namespace std;

char s[N][N];

int w[N][N], sm[N][N], cs[N][N];

int dp[1 << N], n, m;

void dispose() {
for (int i = 0; i < n; i ++ ) {
for (int j = 0; j < m; j ++ ) {
int al = 0, mx = 0;
for (int k = 0; k < n; k ++ ) {
if (s[i][j] == s[k][j]) {
al += w[k][j];
mx = max(mx, w[k][j]);
sm[i][j] |= (1 << k);
}
}
cs[i][j] = al - mx;
}
} memset(dp, 0x3f, sizeof dp); dp[0] = 0;
for (int s = 0; s < (1 << n); s ++ ) {
for (int i = 0; i < n; i ++ ) {
if(!(s >> i & 1)) {
for (int j = 0; j < m; j ++ ) {
dp[s | (1 << i)] = min(dp[s | (1 << i)], dp[s] + w[i][j]);
dp[s | sm[i][j]] = min(dp[s | sm[i][j]], dp[s] + cs[i][j]);
}
break;
}
}
}
} int main() {
cin >> n >> m ;
for (int i = 0; i < n; i ++ ) {
scanf("%s", s[i]);
}
for (int i = 0; i < n; i ++ ) {
for (int j = 0; j < m; j ++ ) {
scanf("%d", &w[i][j]);
}
}
dispose();
printf("%d\n", dp[(1 << n) - 1]);
return 0;
}

小结:最后那个优化的思想其实是很好的,也是一个非常难想到的方法,期待掌握。

[CF544E]Remembering Strings_状压dp的更多相关文章

  1. Codeforces 544E Remembering Strings 状压dp

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

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

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

  3. CF543C Remembering Strings 状压dp

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

  4. BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3336  Solved: 1936[Submit][ ...

  5. nefu1109 游戏争霸赛(状压dp)

    题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...

  6. poj3311 TSP经典状压dp(Traveling Saleman Problem)

    题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...

  7. [NOIP2016]愤怒的小鸟 D2 T3 状压DP

    [NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...

  8. 【BZOJ2073】[POI2004]PRZ 状压DP

    [BZOJ2073][POI2004]PRZ Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍 ...

  9. bzoj3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一(spfa+状压DP)

    数据最多14个有宝藏的地方,所以可以想到用状压dp 可以先预处理出每个i到j的路径中最小权值的最大值dis[i][j] 本来想用Floyd写,无奈太弱调不出来..后来改用spfa 然后进行dp,这基本 ...

随机推荐

  1. 关于JPA动态SQL查询

    1.继承接口 2.下面是简单的操作---自己写过的,下次再整理一下 public Page<IdddsMember> list(MemberSearch search, Pageable ...

  2. 洛谷P3935 Calculation [数论分块]

    题目传送门 格式难调,题面就不放了. 分析: 实际上这个就是这道题的升级版,没什么可讲的,数论分块搞就是了. Code: //It is made by HolseLee on 18th Jul 20 ...

  3. 北京清北 综合强化班 Day2

    a [问题描述] 你是能看到第一题的 friends呢.                                                —— hja世界上没有什么比卖的这 贵弹丸三还令 ...

  4. 「BZOJ 5161」最长上升子序列「状压DP」

    题意 求一个\(1\sim n\)的排列LIS的期望长度,\(n\leq 28\) 题解 考虑朴素的LIS:\(f[i] = min(f[j]) + 1\) 记\(mx[i]\)为\(f\)的前缀最大 ...

  5. 学数据分析到底要不要掌握Linux-Python基础前传(2)

    使用Python的数据分析师到底要不要掌握Linux? 对于上面的问题,大部分的答案是Python数据分析在windows的环境下跑跑就可以了,没有必要再花时间来学习Linux; 这里jacky有一个 ...

  6. python正则表达式的用法

    import re r1 = re.compile(r'(?im)(?P<name></html>)$') content = """ <H ...

  7. loj6519 魔力环

    解题思路 考虑顺时针旋转 \(i\) 步得到的结果,根据Burnside引理,有 \[ Ans=\frac{\sum\limits_{i=0}^{n-1}C(i)}{n} \] \(C(i)\) 为旋 ...

  8. maven整合ssm框架

    1.创建maven web工程 创建完成后,项目结构如下 2.项目配置文件 在pom.xml中添加SSM框架相关jar包的依赖关系,pom.xml代码如下 <?xml version=" ...

  9. Mysql索引查询失效的情况

    首先,复习一下索引的创建: 普通的索引的创建: CREATE INDEX  (自定义)索引名  ON  数据表(字段); 复合索引的创建: CREATE INDEX  (自定义)索引名  ON  数据 ...

  10. spring boot 下 开启 gzip

    [参考文章]:Spring boot开启Gzip压缩 [参考文章]:Accept-Encoding Spring 版本 :5.1.2-RELEASE 1. application.yml 配置 ser ...