[CF543C Round#302 Div.1]Remembering Strings——[状压DP]

【原题】

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 the i-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.

【题目翻译】

你有n条由小写英文字母组成的长度都相同的字符串,一条字符串是容易记住的,定义为这条字符串某个位置上的字符是独一无二的(即所有其他字符串这个位置都没有这个字母,满足一个位置即可)
举个例子,{“abc”, “aba”, “adc”, “ada”} 不容易记忆,{“abc”, “ada”, “ssa”}容易记忆
你可以将这些字符串某些位置上的字符任意替换成另一个字符,这需要花费一些代价,求使所有字符串都容易记忆需要的最小代价。

【输入格式】
第一行两个数字n,m(1<=n,m<=20)
接下来n条长度为m的字符串。
接下来是一个n*m的矩阵表示替换第n条字符串的第m个字符的代价。

【输出格式】
一行,表示答案。

S a m p l e    I n p u t Sample~~Input Sample  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

S a m p l e    O u t p u t Sample~~Output Sample  Output

3

【题意分析】
题意我已经翻译得很明白了吧。。。
这道题比较难想,首先看到n,m都小于等于20,那么可以做到每条字符串都是易于记忆。
考虑状压,用dp[]表示n条字符串易于记忆或者不易于记忆(0不易于,1易于)
那么答案就是dp[(1 << n) - 1]
考虑每条字符串的每一位,我们可以将这位弄成一个与众不同的,或者将其他所有的字符串这一位都改得一样,那显然这位就与众不同了。
common[i][j]表示将第j位和第i条字符串相同的所有字符串(压成二进制)
b[i][j]表示把第j位全搞成一样的最小花费,当然要舍掉一个花费最大的,这个可以预处理。
那么考虑转移
d p [ i ∣ ( 1 &lt; &lt; j ) ] = m i n ( d p [ i ∣ ( 1 &lt; &lt; j ) ] , d p [ i ] + c o s t [ j ] [ k ] ) dp[i|(1&lt;&lt;j)]=min(dp[i|(1&lt;&lt;j)],dp[i]+cost[j][k]) dp[i(1<<j)]=min(dp[i(1<<j)],dp[i]+cost[j][k]) d p [ i ∣ c o m m o n [ j ] [ k ] ] = m i n ( d p [ i ∣ c o m m o n [ j ] [ k ] ] , d p [ i ] + b [ j ] [ k ] ) dp[i|common[j][k]]=min(dp[i|common[j][k]],dp[i]+b[j][k]) dp[icommon[j][k]]=min(dp[icommon[j][k]],dp[i]+b[j][k])

Code:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <algorithm>
#define INF 1 << 22
#define MAXN 30
using namespace std;

char s[MAXN][MAXN];
int data[MAXN][MAXN], common[MAXN][MAXN], b[MAXN][MAXN], dp[INF], n, m;

int main () {
	scanf ("%d%d", &n, &m);
	for (register int i = 0; i < n; i++) scanf ("%s", s[i]);
	for (register int i = 0; i < n; i++)
		for (register int j = 0; j < m; j++)
			scanf ("%d", &data[i][j]);
	for (register int i = 0; i < n; i++)
		for (register int j = 0; j < m; j++) {
			int sum = 0, x = -INF;
			for (register int k = 0; k < n; k++)
				if (s[k][j] == s[i][j]) {
					sum += data[k][j], x = max (x, data[k][j]);
					common[i][j] |= (1 << k);
				}
			b[i][j] = sum - x;
		}
	memset (dp, 0x3f, sizeof (dp)); dp[0] = 0;
	int maxsit = (1 << n);
	for (register int i = 0; i < maxsit; i++)
		for (register int j = 0; j < n; j++)
			if ((i & (1 << j)) == 0)
				for (register int k = 0; k < m; k++) {
					dp[i | (1 << j)] = min (dp[i | (1 << j)], dp[i] + data[j][k]);
					dp[i | common[j][k]] = min (dp[i | common[j][k]], dp[i] + b[j][k]);
				}
	printf ("%d\n", dp[maxsit - 1]);
	return 0;
}
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值