Codeforces544E: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 thei-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 nm (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.

Sample test(s)

input

4 5
abcde
abcde
abcde
abcde
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1

output

3

input

4 3
abc
aba
adc
ada
10 10 10
10 1 10
10 10 10
10 1 10

output

2

input

3 3
abc
ada
ssa
1 1 1
1 1 1
1 1 1

output

0

题意:给出n个长为m的字符串,要求通过改变一些字母,来使得每个字符串,在位置i下的字母与其他串都不一样,给出每个位置改变字母的消耗,要求最小消耗

思路:对于每一个行,我们看每个字符在这一列有几个与其相等的字符,我们就使用两种方案,1是改变这个字符,2是改变除了花费最大的其他字符,然后使用状态压缩去枚举所有情况

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <math.h>
#include <bitset>
#include <algorithm>
#include <climits>
using namespace std;

#define LS 2*i
#define RS 2*i+1
#define UP(i,x,y) for(i=x;i<=y;i++)
#define DOWN(i,x,y) for(i=x;i>=y;i--)
#define MEM(a,x) memset(a,x,sizeof(a))
#define W(a) while(a)
#define LL long long
#define N 25
#define MOD 19999997
#define INF 0x3f3f3f3f
#define EXP 1e-8

char str[N][N];
int a[N][N],cost[N][N];
int dp[1<<21],mark[N][N];

int main()
{
    int i,j,k,n,m;
    scanf("%d%d",&n,&m);
    UP(i,0,n-1)
    {
        scanf("%s",str[i]);
    }
    UP(i,0,n-1)
    {
        UP(j,0,m-1)
        {
            scanf("%d",&a[i][j]);
        }
    }
    MEM(mark,0);
    UP(i,0,n-1)
    {
        UP(k,0,m-1)
        {
            int maxn = 0;
            UP(j,0,n-1)
            {
                if(str[i][k]==str[j][k])
                {
                    mark[i][k]|=(1<<j);
                    cost[i][k]+=a[j][k];
                    maxn = max(maxn,a[j][k]);
                }
            }
            cost[i][k]-=maxn;
        }
    }
    int s = (1<<n);
    UP(i,0,s)
    {
        dp[i] = INF;
    }
    int first;
    dp[0] = 0;
    UP(k,0,s-1)
    {

        for(first=0; k&(1<<first); first++);
        UP(i,0,m-1)
        {
            dp[k|(1<<first)] = min(dp[k|(1<<first)],dp[k]+a[first][i]);
            dp[k|mark[first][i]] = min(dp[k|mark[first][i]],dp[k]+cost[first][i]);
        }

    }
    printf("%d ",dp[s-1]);

    return 0;
}

时间: 2024-12-20 08:31:52

Codeforces544E:Remembering Strings(状态压缩)的相关文章

CSU1611: Concatenation(状态压缩)

Description Zuosige always has bad luck. Recently, he is in hospital because of pneumonia. While he is taking his injection, he feels extremely bored. However, clever Zuosige comes up with a new game. Zuosige writes some of his favorite strings on pa

hdu4758AC自动机+状态压缩DP

http://acm.hdu.edu.cn/showproblem.php?pid=4758 Problem Description On the beaming day of 60th anniversary of NJUST, as a military college which was Second Artillery Academy of Harbin Military Engineering Institute before, queue phalanx is a special l

胜利大逃亡(续)(状态压缩bfs)

胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7357    Accepted Submission(s): 2552 Problem Description Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)……这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带

uva 818(dfs+图+状态压缩)

题意:有n个环,编号从1到n,给出了一些环环相扣的情况,比如给a和b表示a和b两个环的扣在一起的,每个环都是可以打开的,问最少打开多少个环,然后再扣好,可以让所有的环成为一条链. 题解:状态压缩把所有的打开环的情况枚举出来,然后拿去判断是否成立,更新打开环后的图g[i][j],和每个点的度数,不成立有三种情况,1.计算没有打开的环的度数,如果大于2说明不会有链,2.把没有打开环拿去dfs,访问过就vis[i]++,如果vis[i]>=2说明存在环,3.如果打开的环数num + 1小于链的数量,说

POJ 3254 Corn Fields 状态压缩DP (C++/Java)

http://poj.org/problem?id=3254 题目大意: 一个农民有n行m列的地方,每个格子用1代表可以种草地,而0不可以.放牛只能在有草地的,但是相邻的草地不能同时放牛, 问总共有多少种方法. 思路: 状态压缩的DP. 可以用二进制数字来表示放牧情况并判断该状态是否满足条件. 这题的限制条件有两个: 1.草地限制. 2.相邻限制. 对于草地限制,因为输入的时候1是可以种草地的. 以"11110"草地分析,就只有最后一个是不可以种草的.取反后得00001  .(为啥取反

uva 11195 Another queen (用状态压缩解决N后问题)

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2136 Problem A Another n-Queen Problem I guess the n-queen problem is known by every person who has studied backtracking. In this problem you s

dp状态压缩

dp状态压缩 动态规划本来就很抽象,状态的设定和状态的转移都不好把握,而状态压缩的动态规划解决的就是那种状态很多,不容易用一般的方法表示的动态规划问题,这个就更加的难于把握了.难点在于以下几个方面:状态怎么压缩?压缩后怎么表示?怎么转移?是否具有最优子结构?是否满足后效性?涉及到一些位运算的操作,虽然比较抽象,但本质还是动态规划.找准动态规划几个方面的问题,深刻理解动态规划的原理,开动脑筋思考问题.这才是掌握动态规划的关键. 动态规划最关键的要处理的问题就是位运算的操作,容易出错,状态的设计也直

HDU3001(KB2-J 状态压缩dp)

Travelling Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8103    Accepted Submission(s): 2642 Problem Description After coding so many days,Mr Acmer wants to have a good rest.So travelling is

2017盛大游戏杯 零件组装(状态压缩DP之巧妙枚举子集)

题目链接:2017盛大游戏杯 零件组装 题意: 有n个零件,给你相邻关系和排斥关系,每两块零件组装起来有一个代价,问最少的代价总和是多少. 题解: 考虑状态压缩,dp[i]表示i这个集合为一个零件块. 那么要枚举一下i的子集.O(3^n). 先要预处理一下每个集合的排斥个数和相邻个数,然后容斥一下就可以了. 1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,b,sizeof(a)) 3 #define F(i,a,b) for(int