题目链接

题意:

给定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. windows8.1 App中webView 使用定位

    windows8.1的webview的网页中没有办法直接定位  要想定位比较费劲   查了好久才发现一个可行的办法 那就是通过后台代码获取位置信息 然后调用页面中已有的获取位置信息的JS方法 把位置信 ...

  2. eclipse4.2 UI换回 3.6版本的UI

    Apparently, the Eclipse developers were kind enough to leave us an easy way out: From the Window men ...

  3. python之正则表达式备忘

    一简介:就其本质而言,正则表达式(或 RE)是一种小型的.高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现.正则表达式模式被编译成一系列的字节码,然后由用 C ...

  4. Android中的Selector的用法

    转自: Android中的Selector主要是用来改变ListView和Button控件的默认背景.其使用方法可以按一下步骤来设计: (以在mylist_view.xml为例) 1.创建mylist ...

  5. SharePoint 2013 更新多个用户字段(Person or Group)

    有时我们需要更新一个用户到Person or Group类型的字段, 当然这个属性允许设置多个用户, 要如何才能添加新的用户到该字段,同时还不影响原始存在的值. 这里我们需要了解 SPFieldUse ...

  6. Solr4.8.0源码分析(23)之SolrCloud的Recovery策略(四)

    Solr4.8.0源码分析(23)之SolrCloud的Recovery策略(四) 题记:本来计划的SolrCloud的Recovery策略的文章是3篇的,但是没想到Recovery的内容蛮多的,前面 ...

  7. java 反射 动态代理

    在上一篇文章中介绍Java注解的时候,多次提到了Java的反射API.与javax.lang.model不同的是,通过反射API可以获取程序在运行时刻的内部结构.反射API中提供的动态代理也是非常强大 ...

  8. JAVA存取对象属性时,如果开程多线程,记得对相关存取方法作原子化操作定义

    最显著的应用当然是银行存款和取款,不要存在存取数字和实际发生不一样的情况. synchronized关键字. class BankAccount { private int balance = 100 ...

  9. zabbix 参数说明

    <pre name="code" class="html">数据采集的工作模式可以分为被动模式(服务器端到客户端采集数据) 主动模式(客户端主动上报 ...

  10. ♫【HTML5 敏捷实践】第1章 使用语义化的方式实现

    <!DOCTYPE html> 向后兼容的HTML5<doctype>标签.HTML5规范规定<doctype>对大小写不敏感:然而,之前版本的HTML需要< ...