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:
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.
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).
Print a single number — the answer to the problem.
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
3
4 3 abc aba adc ada 10 10 10 10 1 10 10 10 10 10 1 10
2
3 3 abc ada ssa 1 1 1 1 1 1 1 1 1
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; }
Codeforces544E:Remembering Strings(状态压缩)
原文:http://blog.csdn.net/libin56842/article/details/45750407