【DP】【CF1099C】 Postcard
Description
给定一个长度为 \(n\) 的字符串,尽可能包含小写字母,字符 '?' 和字符 ‘*’。保证上面两种特殊字符若出现则一定出现在一个小写字母的后面一位。要求构造一个长度为 \(k\) 的新字符串,它和原串有如下关系:
按照原串的字母顺序向新串中填充,新串中含且仅含小写字母。
若原串的某小写字母后没有特殊字符,则这个字母在新串中必须保留
若原串的某小写字母后有字符 '?',则这个字母在新串中可以被保留,也可以被删除
若原串某小写字母后有字符 '*',则这个字母在新串中可以被保留,可以被删除,也可以被复读很多遍。
Input
第一行是一个长度为 \(n\) 的字符串,保证输入合法
第二行是一个整数 \(k\) 代表要求构造的新串长度
Output
输出一行一个长度为 \(k\) 的字符串,为构造出的串。
若不存在这样的串,输出“Impossible”(不含引号)
Hint
\(1~\leq~n,k~\leq~200\)
Solution
为啥泥萌一个贪心就过了啊qaq,为啥就我一人写了个DP还fst了啊qaq,我咋这么菜啊qaq
我们发现一个字母分别有三种情况:保留,保留/删除,保留/删除/复读。
于是我们处理一个新的字符串,只含给定串中的小写字母,另开数组记录该字母对应哪种情况。一下说的原串均指这个只含小写字母的新串,设原串长度为 \(len\)。
于是问题就被转化为了按照原串一位一位的按照规则填能否填出一个长度为 \(k\) 的字符串。这显然是可以DP的。
其实正着DP大概是可做的,但是比赛的时候有点困就直接倒着DP的。我们设 \(f_{i,j}~=~true/false\) 为能否用原串 \([i,len]\) 位拼出新串的 \([j,k]\) 位。于是转移一共有三种情况:
1、只能保留:
\]
2、保留或删除:
\]
3、保留,删除,复读:
\]
其中 \(\bigvee_{i = a}^{b} s(i)\) 为若 \(\exists~i_0~\in~[a,b],~s.t.~~s(i_0)~=~true\) 则返回 \(true\),否则返回 \(false\)
初始化为 \(f_{len + 1, k + 1} = true\)
在转移时记录一下转移方向就可以输出方案了。
Code
#include <cstdio>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif
#define rg register
#define ci const int
#define cl const long long
typedef long long ll;
namespace IPT {
const int L = 1000000;
char buf[L], *front=buf, *end=buf;
char GetChar() {
if (front == end) {
end = buf + fread(front = buf, 1, L, stdin);
if (front == end) return -1;
}
return *(front++);
}
}
template <typename T>
inline void qr(T &x) {
rg char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
if (lst == '-') x = -x;
}
template <typename T>
inline void ReadDb(T &x) {
rg char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch = IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = x * 10 + (ch ^ 48), ch = IPT::GetChar();
if (ch == '.') {
ch = IPT::GetChar();
double base = 1;
while ((ch >= '0') && (ch <= '9')) x += (ch ^ 48) * ((base *= 0.1)), ch = IPT::GetChar();
}
if (lst == '-') x = -x;
}
namespace OPT {
char buf[120];
}
template <typename T>
inline void qw(T x, const char aft, const bool pt) {
if (x < 0) {x = -x, putchar('-');}
rg int top=0;
do {OPT::buf[++top] = x % 10 + '0';} while (x /= 10);
while (top) putchar(OPT::buf[top--]);
if (pt) putchar(aft);
}
const int maxn = 210;
int Len, k, len;
char MU[maxn], CU[maxn];
int pre[maxn][maxn], vc[maxn];
bool frog[maxn][maxn];
void print(ci, ci);
int main() {
freopen("1.in", "r", stdin);
do MU[++Len] = IPT::GetChar(); while (((MU[Len] >= 'a') && (MU[Len] <= 'z')) || (MU[Len] == '?') || (MU[Len] == '*'));
for (rg int i = 1; i <= Len; ++i) if ((MU[i] >= 'a') && (MU[i] <= 'z')) {
CU[++len] = MU[i];
switch (MU[i + 1]) {
case '?': {
vc[len] = 1;
break;
}
case '*': {
vc[len] = 2;
break;
}
}
}
qr(k);
frog[len + 1][k + 1] = true;
rg int dk = k + 1;
for (rg int i = len; i; --i) {
rg int di = i + 1;
for (rg int j = 1; j <= dk; ++j) {
switch(vc[i]) {
case 0: {
if (frog[di][j + 1]) {
frog[i][j] = true;
pre[i][j] = j + 1;
}
break;
}
case 1: {
if (frog[di][j + 1]) {
frog[i][j] = true;
pre[i][j] = j + 1;
} else if (frog[di][j]) {
frog[i][j] = true;
pre[i][j] = j;
}
break;
}
case 2: {
for (rg int h = j; h <= dk; ++h) if (frog[di][h]) {
frog[i][j] = true;
pre[i][j] = h;
break;
}
break;
}
}
}
}
if (frog[1][1]) print(1, 1);
else puts("Impossible");
return 0;
}
void print(ci cur, ci v) {
if (cur > len) return;
for (rg int i = v; i < pre[cur][v]; ++i) putchar(CU[cur]);
print(cur + 1, pre[cur][v]);
}
【DP】【CF1099C】 Postcard的更多相关文章
- T2980 LR棋盘【Dp+空间/时间优化】
Online Judge:未知 Label:Dp+滚动+前缀和优化 题目描述 有一个长度为1*n的棋盘,有一些棋子在上面,标记为L和R. 每次操作可以把标记为L的棋子,向左移动一格,把标记为R的棋子, ...
- 【10.3校内测试【国庆七天乐!】】【DP+组合数学/容斥】【spfa多起点多终点+二进制分类】
最开始想的暴力DP是把天数作为一个维度所以怎么都没有办法优化,矩阵快速幂也是$O(n^3)$会爆炸. 但是没有想到另一个转移方程:定义$f[i][j]$表示每天都有值的$i$天,共消费出总值$j$的方 ...
- 【DP+树状数组】BZOJ1264-[AHOI2006]基因匹配Match
[题目大意] 给定n个数和两个长度为n*5的序列,两个序列中的数均有1..n组成,且1..n中每个数恰好出现5次,求两个序列的LCS. [思路] 预处理每个数字在a[i]中出现的五个位置.f[i]示以 ...
- BZOJ1079 [SCOI2008]着色方案 【dp记忆化搜索】
题目 有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块. 所有油漆刚好足够涂满所有木块,即c1+c2+-+ck=n.相邻两个木块涂相同色显得很难看 ...
- 【DP|多重背包可行性】POJ-1014 Dividing
Dividing Time Limit: 1000MS Memory Limit: 10000K Description Marsha and Bill own a collection of mar ...
- COGS 862. 二进制数01串【dp+经典二分+字符串】
862. 二进制数01串 ★ 输入文件:kimbits.in 输出文件:kimbits.out 简单对比 时间限制:1 s 内存限制:128 MB USACO/kimbits(译 by ...
- CodeForces - 597C Subsequences 【DP + 树状数组】
题目链接 http://codeforces.com/problemset/problem/597/C 题意 给出一个n 一个 k 求 n 个数中 长度为k的上升子序列 有多少个 思路 刚开始就是想用 ...
- hihocoder1475 数组分拆【DP+前缀和优化】
思路: DP[ i ] 代表以 i 结尾的方案数. dp[i] += sum[i] - sum[j - 1] != 0 ? dp[j] : 0 ; 对于100%的数据,满足1<=N<=10 ...
- SPOJ130 【DP·背包选取特性】
题意: 给你n个任务,每个任务有一个起始时间,持续时间,一个权值: 问你怎么分配得到最大值 思路: 数据好大..百度了一发意识到自己好菜啊!背包的特性. dp[i]代表前 i 个能构成的最大值. 对于 ...
- lightoj1145 【DP优化求方案】
题意: 有一个k面的骰子,然后问你n个骰子朝上的面数字之和=s的方案: 思路: dp[i][j] 代表 前 i 个骰子组成 j 有多少种方案: 显然 dp[i][j] = dp[i - 1][j - ...
随机推荐
- 从零开始的Python学习Episode 17——序列化
序列化 我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语 言中也被称之为serialization,marshalling,flattenin ...
- Python处理PDF和Word文档常用的方法
Python处理PDF和Word文档的模块是PyPDF2,使用之前需要先导入. 打开一个PDF文档的操作顺序是:用open()函数打开文件并用一个变量来接收,然后把变量给传递给PdfFileReade ...
- MySQL基础(一)
首先需要安装MySOL,这里我是在windows环境下安装的,具体教程可以参考https://www.cnblogs.com/xsmile/p/7753984.html,不过要注意安装过程可能会不太顺 ...
- rename命令详解
基础命令学习目录首页 原文链接:http://man.linuxde.net/rename 将main1.c重命名为main.c rename main1.c main.c main1.c renam ...
- 手动搭建一个webpack+react笔记
{ "name": "lottery", "version": "1.0.0", "description&q ...
- 5337朱荟潼Java实验报告一
一.实验内容 1.内容一输出“Hello 名”. import java.util.Scanner;public class Hello{public static void main(String[ ...
- 20172301 2017-2018-2 《程序设计与数据结构》实验一《Java开发环境的熟悉》实验报告
20172301 2017-2018-2 <程序设计与数据结构>实验一<Java开发环境的熟悉>实验报告 课程:<程序设计与数据结构> 班级: 1723 姓名: 郭 ...
- AbstractFactory(PeopleSkin)
使用抽象工厂模式,完成下述产品等级结构: 实现 UML类图 public class BlackFactory implements MWFactory{ public Man produceMan( ...
- Week4-作业1
第四章 这一章主要讲了代码规范.复审和团队合作这两项内容. 在关于代码设计规范方面,书中讲到了关于goto的使用: “函数最好有单一的出口,为了达到这一目的, ...
- Beta阶段——第四篇 Scrum 冲刺博客
i. 提供当天站立式会议照片一张: ii. 每个人的工作 (有work item 的ID) (1) 昨天已完成的工作: 充值与账单的数据库操作结合,实现余额功能 (2) 今天计划完成的工作: 用户权限 ...