题目链接

题意:

给定n个长度均为m的字符串

以下n行给出字符串

以下n*m的矩阵表示把相应的字母改动成其它字母的花费。

问:

对于一个字符串,若它是easy to remembering 当 它存在一个字母。使得这个字母在这一列是独一无二的。

要使得n个字符串都是easy to remembering 的最小花费。

第一个例子是把第一列的4个a中3个a改动成别的字母。所以花费为3.

思路:

显然是个状压dp,但须要一点转化。

首先得到一个结论:

对于某一列,设这一列的字母是 a,a,b,b,a,d,c···

随意改动某种字母,都能使得包含该种字母的字符串变成unique

instance: 把全部的a字母都改动为别的字母,一定能使得改动后的字母与同列的其它字母不反复。

由于最多仅仅有20个字符串,也就是改动后的字母种类至多仅仅有20种。

然后状压已经easy to remembering的字符串的最小花费。

dp[i] 表示已经easy to remembering 的字符串状态为i时的最小花费。

两个转移:

1、直接改动字母

2、把这一列中全部与这个字母同样的字母都改动成别的字母。

当然能够剩下一个,剩下花费最大的那个就可以。

cost[i][j] 就表示除了花费最大的那个 同列中与str[i][j]字母同样的花费和。

bit[i][j] 表示哪些字符串 在第j列 与 a[i][j] 字母同样。

#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <cstdio>
#include <map>
#include <queue>
#include <algorithm>
#include <stack>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
using namespace std;
template <class T>
inline bool rd(T &ret) {
char c; int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c<'0' || c>'9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
template <class T>
inline void pt(T x) {
if (x <0) {
putchar('-');
x = -x;
}
if (x>9) pt(x / 10);
putchar(x % 10 + '0');
}
typedef long long ll;
typedef pair<ll, ll> pii;
const int inf = 1e9;
const int N = 21;
int n, m;
char s[N][N];
int a[N][N];
int dp[1 << N];
int bit[N][N], cost[N][N];
int main() {
rd(n); rd(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++)rd(a[i][j]);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
{
int ans = 0, maxn = -inf;
for (int k = 0; k < n; k++)
if (s[i][j] == s[k][j])
{
ans += a[k][j];
maxn = max(maxn, a[k][j]);
bit[i][j] |= 1 << k;
}
ans -= maxn;
cost[i][j] = ans;
}
for (int i = 1; i < (1 << n); i++)dp[i] = inf;
dp[0] = 0;
for (int i = 0; i < (1 << n); i++)
{
for (int j = 0; j < n; j++)
if ((i & (1 << j)) == 0)
{
for (int k = 0; k < m; k++)
{
dp[i | (1 << j)] = min(dp[i | (1 << j)], dp[i] + a[j][k]);
dp[i | bit[j][k]] = min(dp[i | bit[j][k]], dp[i] + cost[j][k]);
}
}
}
pt(dp[(1 << n) - 1]);
return 0;
}

Codeforces 544E Remembering Strings 状压dp的更多相关文章

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

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

  2. CF543C Remembering Strings 状压dp

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

  3. codeforces Diagrams & Tableaux1 (状压DP)

    http://codeforces.com/gym/100405 D题 题在pdf里 codeforces.com/gym/100405/attachments/download/2331/20132 ...

  4. Codeforces 917C - Pollywog(状压 dp+矩阵优化)

    UPD 2021.4.9:修了个 typo,为啥写题解老出现 typo 啊( Codeforces 题目传送门 & 洛谷题目传送门 这是一道 *2900 的 D1C,不过还是被我想出来了 u1 ...

  5. Codeforces 79D - Password(状压 dp+差分转化)

    Codeforces 题目传送门 & 洛谷题目传送门 一个远古场的 *2800,在现在看来大概 *2600 左右罢( 不过我写这篇题解的原因大概是因为这题教会了我一个套路罢( 首先注意到每次翻 ...

  6. codeforces 21D. Traveling Graph 状压dp

    题目链接 题目大意: 给一个无向图, n个点m条边, 每条边有权值, 问你从1出发, 每条边至少走一次, 最终回到点1. 所走的距离最短是多少. 如果这个图是一个欧拉回路, 即所有点的度数为偶数. 那 ...

  7. Codeforces 895C - Square Subsets 状压DP

    题意: 给了n个数,要求有几个子集使子集中元素的和为一个数的平方. 题解: 因为每个数都可以分解为质数的乘积,所有的数都小于70,所以在小于70的数中一共只有19个质数.可以使用状压DP,每一位上0表 ...

  8. CodeForces 327E Axis Walking(状压DP+卡常技巧)

    Iahub wants to meet his girlfriend Iahubina. They both live in Ox axis (the horizontal axis). Iahub ...

  9. Codeforces ----- Kefa and Dishes [状压dp]

    题目传送门:580D 题目大意:给你n道菜以及每道菜一个权值,k个条件,即第y道菜在第x道后马上吃有z的附加值,求从中取m道菜的最大权值 看到这道题,我们会想到去枚举,但是很显然这是会超时的,再一看数 ...

随机推荐

  1. SGU 177.Square(矩阵分割)

    时间限制:1.25s 空间限制:6M 题意: 给出n*n的矩阵(n<=1000),和m次涂色(m<=5000),每次涂色将一个子矩阵涂成白色或黑色,后涂的颜色将覆盖掉前面的颜色.初始所有格 ...

  2. sed 简明教程

    做个标记 http://coolshell.cn/articles/9104.html sed全名叫stream editor,流编辑器,用程序的方式来编辑文本,相当的hacker啊.sed基本上就是 ...

  3. Centos JAVA Eclipse

    wget http://download.oracle.com/otn-pub/java/jdk/8u5-b13/jdk-8u5-linux-i586.tar.gz vi /etc/profile 在 ...

  4. phpstorm IDE编辑器使用手记

    a.选项卡限制问题 突破打开的文件选项卡个数限制:默认安装后的phpstorm打开的文件个数是有限制的,默认是10个.也就是最多同时打开10个文件进行编辑. 超过10个就会自动关闭前面最先打开的文件. ...

  5. eval函数:分号的应用

    eval("echo'hello world';"); ("参数;") eval函数把参数当做php代码来执行,参数后要有分号,最后还要另加一个分号 相当于: ...

  6. php把文件上传到远程服务器上例子

    在这里我们利用curl实现把本地服务器的文件通过curl发送请求给远程服务器的php文件接受就实现了上传,还一个是利用ftp来上传方法也是php中的curl操作ftp服务器进行上传. 我这里写的是用c ...

  7. DDoS攻击

    来自百度百科 分布式拒绝服务攻击编辑 分布式拒绝服务攻击(英文:Distributed Denial of Service,缩写:DDoS)亦称洪水攻击.顾名思义,即是利用网络上已被攻陷的电脑作为“僵 ...

  8. Python Tutorial 学习(四)--More Control Flow Tools

    4.1 if 表达式 作为最为人熟知的if.你肯定对这样的一些表达式不感到陌生: >>> x = int(raw_input("Please enter an intege ...

  9. java学习之 垃圾回收

    垃圾回收器始终以一个较低优先级的后台进程进行垃圾的回收工作,这样不会影响程序的正常工作. 通常只有当内存到达用尽的边缘而程序需要分配新的内存空间时,垃圾回收器才会执行. 垃圾回收的条件:1,垃圾回收器 ...

  10. Java高精度学习第二弹——求N!

    继续学习Java高精度,今天写的是求N!. 首先附上源代码: import java.util.Scanner; import java.math.BigInteger; public class M ...