CF70B Text Messaging 题解

题目传送门

题意简介

有以下递归定义:

消息 = 句子 or 句子 空格 消息
句子 = 单词 空格 句子 or 单词 结尾
结尾 = {'.', '?', '!'}
单词 = 字母 or 字母 单词
字母 = {'a'..'z', 'A'..'Z'}
空格 = ' '
(结尾为句子结尾。)

现在有一个字符串 $s$,问最少将 $s$ 拆分成多少个长度不超过 $n$ 的消息发出。

解法

思路

首先 $s$ 中的句子明显不可以调换顺序,所以只有相邻的句子能合并成一个消息。

具体地说,如果两个相邻的句子或消息 $a$ 和 $b$,若 $|a|+1+|b|\le n$,则可合并为 $a+b$。当然,合并后的消息也可以再次合并

注意:两个长度相加要再加 $1$,因为消息的定义之一为 消息 = 句子 空格 消息,空格也占一个长度。

所有句子的内容在本题中并不重要,只需知道它们的长度即可。

算法流程

  • 首先读入 $n,s$,处理出 $s$ 中每个句子的长度。
  • 将第一个句子的长度存入 vector 中。
  • 若还有句子,则尝试合并。
    • 如果两个相邻的句子或消息的长度相加再加 $1$ 小于等于 $n$,则合并。
  • 继续合并。

代码

有注释。

#include <iostream>
#include <string>
#include <vector>
using namespace std;
#define c s[i]
int main()
{
int n;
scanf("%d\n",&n);//一定要读入回车,否则 getline 会出错
string s;
getline(cin,s);//读入一整行
int len=0,siz=s.size();//len:当前句子长度 siz:整个字符串长度
vector<int> mes;
for(int i=0;i<siz;i++)
{
if(c=='.'||c=='?'||c=='!')//如果句子结束
{
len++;
if(len>n)//如果超限,输出不可能
{
puts("Impossible");
return 0;
}
if(!mes.empty()&&mes.back()+len+1<=n)//能合并
{
mes.back()+=(len+1);//就合并
}
else
{
mes.push_back(len);//创建新消息
}
// printf("%d\n",len);
i++;//跳过空格
len=0;
}
else
{
len++;//否则长度加 1
}
}
printf("%d\n",mes.size());//输出消息数量
return 0;
}
posted @   Po7ed  阅读(6)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示