题意:
给定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; }