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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具