#4009. 「2018-8-26 联考」01 串 (kushi)

题目描述
定义一个关于 01 串的函数 如下:

空串;
,其中 为一个 01 串;
, 为最短的满足 是 的前缀且 是 的后缀的 01 串,例如 ;

现有一个由 个 01 串组成的序列 ,你需要将其恰好分为两个子序列 和 ,不改变串之间的相对顺序,使得 尽量小,其中 表示 的长度。子序列可以为空。

输入格式
从文件 kushi.in 中读入数据。

第一行两个正整数 ,其中 表示每个 01 串的长度。
接下来 行,每行一个长度为 的 01 串,表示 。

输出格式
输出到文件 kushi.out 中。

输出一个整数,表示最小的要求最小化的值。

样例
样例输入

4 3
000
111
110
001
样例输出

8
数据范围与提示
对于 的数据,,。
对于 的数据,,。
对于 的数据,,。

分类标签
省内联考 2018
题解:
#include
#include
#define M 2097152
#define N 200002
inline void min(int& x, int y) {
if (y < x)
x = y;
}
int f[M], i, j, k, l, m, n, s, x;
char c[21];
int main() {
freopen(“kushi.in”, “r”, stdin), freopen(“kushi.out”, “w”, stdout);
if (scanf(“%d%d”, &n, &m), n == 0)
return 0 & puts(“0”);
if (memset(f, 0x3f, 8 << m), n == 1)
return 0 & printf(“%d\n”, m);
for (scanf(“%s”, c), i = 0; i < m; i++) k |= (c[i] ^ 48) << i;
for (s = m, i = 2; i <= n; i++, k = l, l = 0) {
for (scanf(“%s”, c), j = 0; j < m; j++) l |= (c[j] ^ 48) << j;
for (j = 0, x = s + m; j <= m; j++) min(x, f[l & (1 << j) - 1 | 1 << j] + s + m - j);
for (j = m;; j–)
if (k >> m - j == (l & (1 << j) - 1)) {
s += m - j;
break;
}
for (j = 0; j <= m; j++) min(f[k >> m - j | 1 << j], x - s);
}
for (i = 0, x = s; i < 1 << m; i++) min(x, f[i | 1 << m] + s);
return 0 & printf(“%d\n”, x);
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值