题意:
给定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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-04 22:52:25