├── 试手练习 ├── 流感.cpp ├── 分数求和.cpp ├── 喝奶茶.cpp ├── 大象喝水.cpp ├── 循环数.cpp ├── 换酒问题.cpp ├── 最短前缀.cpp ├── 田忌赛马.cpp ├── 破解密码.cpp ├── 统计字符.cpp ├── 花生问题.cpp ├── 计数问题.cpp ├── 试剂稀释.cpp ├── 过河问题.cpp ├── 重排空格.cpp ├── 小于当前数的数.cpp ├── 小茗同学很方.cpp ├── 最大数输出.cpp ├── 最简真分数序列.cpp ├── 有趣的二进制.cpp ├── 温度表达变化.cpp ├── 甲流病人初筛.cpp ├── 计算平均年龄.cpp ├── ngram串频统计.cpp ├── 回型加密十进制版.cpp ├── 谁能拿到最多的硬币.cpp ├── ab problem.cpp ├── 放苹果问题.cpp └── 前缀表达式.cpp ├── 期中考试 ├── 门诊计数.cpp ├── 啤酒厂选址.cpp ├── 是否中闪电.cpp ├── 有效的密码.cpp ├── 海龟去哪儿了.cpp ├── 细菌实验分组.cpp ├── 带符号的大整数相减.cpp ├── 柱状图上的最大矩形.cpp └── 判断是否为C语言的合法标识符.cpp ├── 第一次模拟考试 ├── 井底之蛙.cpp ├── 求交集.cpp ├── 流感传染.cpp ├── 确定进制.cpp ├── 话题焦点.cpp ├── 回文数判断.cpp ├── 密切数判断.cpp ├── 细菌的战争.cpp └── 营养与健康.cpp ├── 第三阶段编程练习1 ├── 拔牙.cpp ├── 角谷猜想.cpp ├── 回文数判断.cpp ├── 孙悟空找师傅.cpp └── 最小公倍数.cpp ├── 第三阶段编程练习3 ├── 拔牙.cpp ├── 二叉树.cpp ├── 分解因数.cpp ├── 集合里的乘法.cpp ├── 回文字符串.cpp ├── 和为定值的子集数.cpp ├── 回数猜想.cpp ├── 排队游戏.cpp ├── 水淹七军.cpp └── 棋盘问题.cpp ├── 第二次模拟考试 ├── 好人坏人.cpp ├── 矩形覆盖.cpp ├── 打鱼还是晒网.cpp ├── 有趣的二进制.cpp ├── 校门外的树.cpp ├── 1020跳格问题.cpp ├── 487-3279.cpp ├── 五子棋判断输赢.cpp └── 区间合并20版本.cpp ├── 2021年期中考试题 ├── 日期串.cpp ├── 操作数列.cpp ├── 数字消失.cpp ├── 最匹配的矩阵.cpp ├── 病人分类.cpp ├── 节约网费.cpp ├── 邮局选址.cpp ├── 魔王军队.cpp ├── 操作数列_BST.cpp ├── 爱读书的Tim.cpp └── 操作数列_MinHeap.cpp ├── 第一阶段编程练习1 ├── 北京地铁.cpp ├── 房价vs年薪.cpp ├── 斐波那契数列.cpp ├── 最受欢迎的医生.cpp ├── 点和正方形的关系.cpp └── 能被357整除的数.cpp ├── 第一阶段编程练习2 ├── 两数之和.cpp ├── 数组逆序.cpp ├── 计算书费.cpp ├── 最小最大数之差.cpp ├── 石头剪子布.cpp ├── 计算abc的值.cpp └── 不与最大数相同的数字之和.cpp ├── 第一阶段编程练习3 ├── 完美立方.cpp ├── 画矩形.cpp ├── 哥德巴赫猜想.cpp ├── 骑车与走路.cpp ├── 分离整数的各个数位.cpp └── 统计满足条件的4位数个数.cpp ├── 第一阶段编程练习4 ├── 求亲和数.cpp ├── 煎鸡排.cpp ├── 判断四边形.cpp ├── 找到不一样的数.cpp ├── 牛顿迭代方法.cpp ├── 一种等价类划分问题.cpp └── 三个三位数的关系.cpp ├── 第三阶段编程练习2 ├── 红与黑.cpp ├── 取石子游戏.cpp ├── 后缀表达式.cpp ├── 字符串p型编码.cpp ├── 查看菌落数目.cpp ├── 猴子分苹果.cpp └── 计算x的n阶勒让德多项式.cpp ├── 第二阶段编程练习1 ├── 开关电灯.cpp ├── 快速找零.cpp ├── 最长平台.cpp ├── 跳绳游戏.cpp ├── 招聘会人数.cpp ├── 校门外的树.cpp └── 求特殊自然数.cpp ├── 第二阶段编程练习2 ├── 肿瘤检测.cpp ├── 二进制加法.cpp ├── 计算数据的方差.cpp ├── 二维数组回形遍历.cpp ├── 统计字母和数字个数.cpp └── 计算两个日期之间的天数.cpp ├── 第二阶段编程练习3 ├── 出书最多.cpp ├── 单词倒排.cpp ├── 肿瘤面积.cpp ├── 寻找平面上的极大点.cpp ├── 判断字符串是否为回文.cpp └── 提取数字串按数值排序.cpp ├── 第二阶段编程练习4 ├── 判断闰年.cpp ├── 单词翻转.cpp ├── 子串定位.cpp ├── 挂号医师.cpp ├── 文字排版.cpp ├── 比饭量.cpp ├── 活动选择.cpp ├── 统计单词.cpp ├── 计算鞍点.cpp ├── 跳水比赛.cpp ├── 进制计算.cpp ├── 五户共井问题.cpp ├── 密切数判断.cpp ├── 根据日期求星期.cpp ├── 侃侃而谈的四位朋友.cpp └── 将两个排序后的数组合并.cpp ├── 第二阶段编程练习5 ├── 传球游戏.cpp ├── 排队看病.cpp ├── 相关月.cpp ├── 佩奇的勇气机.cpp ├── 变幻的矩阵.cpp ├── 垂直直方图.cpp ├── 字符串最大跨距.cpp └── 简单的缩略语判断.cpp ├── 2020年期中考试题 ├── 小茗同学很方.cpp ├── 换酒问题.cpp ├── 最短前缀.cpp ├── 甲流病人初筛.cpp ├── 破解密码.cpp ├── 花生问题.cpp ├── 过河问题.cpp ├── 重排空格.cpp └── 小于当前数的数.cpp ├── .gitignore ├── 2021年期末考试题 ├── 购买纪念品.cpp ├── 发水果.cpp ├── 天平.cpp ├── 盗宝.cpp ├── 城堡问题.cpp ├── 最小外包矩形.cpp ├── 任意K进制长纯小数加法运算.cpp ├── 装载问题.cpp └── 拨钟问题.cpp ├── 2020年期末考试题 ├── 最长连号.cpp ├── 括号配对.cpp ├── 求到最大最小值距离差最小的数.cpp ├── 计算字符串的相似度.cpp ├── 特殊素数序列.cpp ├── 对角遍历.cpp ├── DNA排序.cpp ├── 球桌出租.cpp └── 拼装模型.cpp ├── 综合练习 ├── 最小公倍数.cpp ├── 检查队伍.cpp ├── 最短歧义串.cpp ├── 迷信的病人.cpp ├── 笨小嗨.cpp ├── 简单括号匹配.cpp ├── 鹰蛋.cpp ├── 山区建小学.cpp ├── Unix纪元.cpp ├── 求最长回文子串.cpp ├── 缩小积木.cpp ├── 数组区域数目问题.cpp ├── 连续邮资问题.cpp ├── 代码查重.cpp ├── 矩阵乘方和.cpp ├── 循环数.cpp ├── ngram串频统计.cpp ├── 有效地密码.cpp └── 人工智能.cpp ├── 第四阶段编程练习1 ├── 计算2的N次方.cpp ├── 寻找最长公共前缀.cpp ├── 购买礼物.cpp ├── 石子归并.cpp ├── 自己动手丰衣足食.cpp ├── 土豪的月收入.cpp ├── 最优路径.cpp ├── 采药.cpp ├── 矩阵乘法(使用指针完成).cpp └── 马和电话.cpp ├── LICENSE ├── 期末考试 ├── 阶梯电价购电.cpp ├── 世界杯赢家.cpp ├── 佳佳的筷子.cpp ├── 炸鸡排.cpp ├── 世界杯只因.cpp ├── 合理的饭票设计.cpp ├── 四则运算表达式的值.cpp ├── 请佩戴好口罩.cpp └── 罗马数字与整数的转换.cpp ├── 第三阶段编程练习5 ├── 插入乘号.cpp ├── 求数组不相邻元素之和的最大值.cpp ├── 最长公共子序列.cpp ├── 钢条切割问题.cpp ├── 元素和最大的子矩阵.cpp ├── 合唱队形.cpp ├── 最优路径.cpp ├── 鸡蛋的硬度.cpp └── 矩阵取数游戏.cpp ├── 第三阶段编程练习4 ├── 分割乘积.cpp ├── 查看菌落数目.cpp ├── 子集合划分.cpp ├── 八皇后.cpp ├── 平衡矩阵.cpp ├── 分词.cpp ├── 图案计数.cpp └── 左手定则.cpp └── 第四阶段编程练习2 ├── 检查队伍.cpp ├── 简单括号匹配.cpp ├── 鹰蛋.cpp ├── Unix纪元.cpp ├── 缩小积木.cpp ├── 数组区域数目问题.cpp ├── 求最长回文子串.cpp ├── 循环数.cpp ├── 人工智能.cpp └── 矩阵乘方和.cpp /试手练习/流感.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/流感.cpp -------------------------------------------------------------------------------- /期中考试/门诊计数.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/期中考试/门诊计数.cpp -------------------------------------------------------------------------------- /试手练习/分数求和.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/分数求和.cpp -------------------------------------------------------------------------------- /试手练习/喝奶茶.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/喝奶茶.cpp -------------------------------------------------------------------------------- /试手练习/大象喝水.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/大象喝水.cpp -------------------------------------------------------------------------------- /试手练习/循环数.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/循环数.cpp -------------------------------------------------------------------------------- /试手练习/换酒问题.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/换酒问题.cpp -------------------------------------------------------------------------------- /试手练习/最短前缀.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/最短前缀.cpp -------------------------------------------------------------------------------- /试手练习/田忌赛马.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/田忌赛马.cpp -------------------------------------------------------------------------------- /试手练习/破解密码.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/破解密码.cpp -------------------------------------------------------------------------------- /试手练习/统计字符.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/统计字符.cpp -------------------------------------------------------------------------------- /试手练习/花生问题.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/花生问题.cpp -------------------------------------------------------------------------------- /试手练习/计数问题.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/计数问题.cpp -------------------------------------------------------------------------------- /试手练习/试剂稀释.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/试剂稀释.cpp -------------------------------------------------------------------------------- /试手练习/过河问题.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/过河问题.cpp -------------------------------------------------------------------------------- /试手练习/重排空格.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/重排空格.cpp -------------------------------------------------------------------------------- /期中考试/啤酒厂选址.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/期中考试/啤酒厂选址.cpp -------------------------------------------------------------------------------- /期中考试/是否中闪电.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/期中考试/是否中闪电.cpp -------------------------------------------------------------------------------- /期中考试/有效的密码.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/期中考试/有效的密码.cpp -------------------------------------------------------------------------------- /期中考试/海龟去哪儿了.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/期中考试/海龟去哪儿了.cpp -------------------------------------------------------------------------------- /期中考试/细菌实验分组.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/期中考试/细菌实验分组.cpp -------------------------------------------------------------------------------- /第一次模拟考试/井底之蛙.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一次模拟考试/井底之蛙.cpp -------------------------------------------------------------------------------- /第一次模拟考试/求交集.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一次模拟考试/求交集.cpp -------------------------------------------------------------------------------- /第一次模拟考试/流感传染.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一次模拟考试/流感传染.cpp -------------------------------------------------------------------------------- /第一次模拟考试/确定进制.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一次模拟考试/确定进制.cpp -------------------------------------------------------------------------------- /第一次模拟考试/话题焦点.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一次模拟考试/话题焦点.cpp -------------------------------------------------------------------------------- /第三阶段编程练习1/拔牙.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第三阶段编程练习1/拔牙.cpp -------------------------------------------------------------------------------- /第三阶段编程练习3/拔牙.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第三阶段编程练习3/拔牙.cpp -------------------------------------------------------------------------------- /第二次模拟考试/好人坏人.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二次模拟考试/好人坏人.cpp -------------------------------------------------------------------------------- /第二次模拟考试/矩形覆盖.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二次模拟考试/矩形覆盖.cpp -------------------------------------------------------------------------------- /试手练习/小于当前数的数.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/小于当前数的数.cpp -------------------------------------------------------------------------------- /试手练习/小茗同学很方.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/小茗同学很方.cpp -------------------------------------------------------------------------------- /试手练习/最大数输出.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/最大数输出.cpp -------------------------------------------------------------------------------- /试手练习/最简真分数序列.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/最简真分数序列.cpp -------------------------------------------------------------------------------- /试手练习/有趣的二进制.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/有趣的二进制.cpp -------------------------------------------------------------------------------- /试手练习/温度表达变化.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/温度表达变化.cpp -------------------------------------------------------------------------------- /试手练习/甲流病人初筛.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/甲流病人初筛.cpp -------------------------------------------------------------------------------- /试手练习/计算平均年龄.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/计算平均年龄.cpp -------------------------------------------------------------------------------- /2021年期中考试题/日期串.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2021年期中考试题/日期串.cpp -------------------------------------------------------------------------------- /期中考试/带符号的大整数相减.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/期中考试/带符号的大整数相减.cpp -------------------------------------------------------------------------------- /期中考试/柱状图上的最大矩形.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/期中考试/柱状图上的最大矩形.cpp -------------------------------------------------------------------------------- /第一次模拟考试/回文数判断.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一次模拟考试/回文数判断.cpp -------------------------------------------------------------------------------- /第一次模拟考试/密切数判断.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一次模拟考试/密切数判断.cpp -------------------------------------------------------------------------------- /第一次模拟考试/细菌的战争.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一次模拟考试/细菌的战争.cpp -------------------------------------------------------------------------------- /第一次模拟考试/营养与健康.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一次模拟考试/营养与健康.cpp -------------------------------------------------------------------------------- /第一阶段编程练习1/北京地铁.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习1/北京地铁.cpp -------------------------------------------------------------------------------- /第一阶段编程练习2/两数之和.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习2/两数之和.cpp -------------------------------------------------------------------------------- /第一阶段编程练习2/数组逆序.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习2/数组逆序.cpp -------------------------------------------------------------------------------- /第一阶段编程练习2/计算书费.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习2/计算书费.cpp -------------------------------------------------------------------------------- /第一阶段编程练习3/完美立方.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习3/完美立方.cpp -------------------------------------------------------------------------------- /第一阶段编程练习3/画矩形.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习3/画矩形.cpp -------------------------------------------------------------------------------- /第一阶段编程练习4/求亲和数.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习4/求亲和数.cpp -------------------------------------------------------------------------------- /第一阶段编程练习4/煎鸡排.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习4/煎鸡排.cpp -------------------------------------------------------------------------------- /第三阶段编程练习1/角谷猜想.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第三阶段编程练习1/角谷猜想.cpp -------------------------------------------------------------------------------- /第三阶段编程练习2/红与黑.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第三阶段编程练习2/红与黑.cpp -------------------------------------------------------------------------------- /第二次模拟考试/打鱼还是晒网.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二次模拟考试/打鱼还是晒网.cpp -------------------------------------------------------------------------------- /第二次模拟考试/有趣的二进制.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二次模拟考试/有趣的二进制.cpp -------------------------------------------------------------------------------- /第二次模拟考试/校门外的树.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二次模拟考试/校门外的树.cpp -------------------------------------------------------------------------------- /第二阶段编程练习1/开关电灯.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习1/开关电灯.cpp -------------------------------------------------------------------------------- /第二阶段编程练习1/快速找零.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习1/快速找零.cpp -------------------------------------------------------------------------------- /第二阶段编程练习1/最长平台.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习1/最长平台.cpp -------------------------------------------------------------------------------- /第二阶段编程练习1/跳绳游戏.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习1/跳绳游戏.cpp -------------------------------------------------------------------------------- /第二阶段编程练习2/肿瘤检测.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习2/肿瘤检测.cpp -------------------------------------------------------------------------------- /第二阶段编程练习3/出书最多.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习3/出书最多.cpp -------------------------------------------------------------------------------- /第二阶段编程练习3/单词倒排.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习3/单词倒排.cpp -------------------------------------------------------------------------------- /第二阶段编程练习3/肿瘤面积.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习3/肿瘤面积.cpp -------------------------------------------------------------------------------- /第二阶段编程练习4/判断闰年.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习4/判断闰年.cpp -------------------------------------------------------------------------------- /第二阶段编程练习4/单词翻转.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习4/单词翻转.cpp -------------------------------------------------------------------------------- /第二阶段编程练习4/子串定位.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习4/子串定位.cpp -------------------------------------------------------------------------------- /第二阶段编程练习4/挂号医师.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习4/挂号医师.cpp -------------------------------------------------------------------------------- /第二阶段编程练习4/文字排版.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习4/文字排版.cpp -------------------------------------------------------------------------------- /第二阶段编程练习4/比饭量.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习4/比饭量.cpp -------------------------------------------------------------------------------- /第二阶段编程练习4/活动选择.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习4/活动选择.cpp -------------------------------------------------------------------------------- /第二阶段编程练习4/统计单词.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习4/统计单词.cpp -------------------------------------------------------------------------------- /第二阶段编程练习4/计算鞍点.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习4/计算鞍点.cpp -------------------------------------------------------------------------------- /第二阶段编程练习4/跳水比赛.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习4/跳水比赛.cpp -------------------------------------------------------------------------------- /第二阶段编程练习4/进制计算.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习4/进制计算.cpp -------------------------------------------------------------------------------- /第二阶段编程练习5/传球游戏.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习5/传球游戏.cpp -------------------------------------------------------------------------------- /第二阶段编程练习5/排队看病.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习5/排队看病.cpp -------------------------------------------------------------------------------- /第二阶段编程练习5/相关月.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习5/相关月.cpp -------------------------------------------------------------------------------- /试手练习/ngram串频统计.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/ngram串频统计.cpp -------------------------------------------------------------------------------- /试手练习/回型加密十进制版.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/回型加密十进制版.cpp -------------------------------------------------------------------------------- /试手练习/谁能拿到最多的硬币.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/谁能拿到最多的硬币.cpp -------------------------------------------------------------------------------- /2020年期中考试题/小茗同学很方.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2020年期中考试题/小茗同学很方.cpp -------------------------------------------------------------------------------- /2020年期中考试题/换酒问题.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2020年期中考试题/换酒问题.cpp -------------------------------------------------------------------------------- /2020年期中考试题/最短前缀.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2020年期中考试题/最短前缀.cpp -------------------------------------------------------------------------------- /2020年期中考试题/甲流病人初筛.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2020年期中考试题/甲流病人初筛.cpp -------------------------------------------------------------------------------- /2020年期中考试题/破解密码.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2020年期中考试题/破解密码.cpp -------------------------------------------------------------------------------- /2020年期中考试题/花生问题.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2020年期中考试题/花生问题.cpp -------------------------------------------------------------------------------- /2020年期中考试题/过河问题.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2020年期中考试题/过河问题.cpp -------------------------------------------------------------------------------- /2020年期中考试题/重排空格.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2020年期中考试题/重排空格.cpp -------------------------------------------------------------------------------- /2021年期中考试题/操作数列.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2021年期中考试题/操作数列.cpp -------------------------------------------------------------------------------- /2021年期中考试题/数字消失.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2021年期中考试题/数字消失.cpp -------------------------------------------------------------------------------- /2021年期中考试题/最匹配的矩阵.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2021年期中考试题/最匹配的矩阵.cpp -------------------------------------------------------------------------------- /2021年期中考试题/病人分类.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2021年期中考试题/病人分类.cpp -------------------------------------------------------------------------------- /2021年期中考试题/节约网费.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2021年期中考试题/节约网费.cpp -------------------------------------------------------------------------------- /2021年期中考试题/邮局选址.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2021年期中考试题/邮局选址.cpp -------------------------------------------------------------------------------- /2021年期中考试题/魔王军队.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2021年期中考试题/魔王军队.cpp -------------------------------------------------------------------------------- /第一阶段编程练习1/房价vs年薪.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习1/房价vs年薪.cpp -------------------------------------------------------------------------------- /第一阶段编程练习1/斐波那契数列.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习1/斐波那契数列.cpp -------------------------------------------------------------------------------- /第一阶段编程练习1/最受欢迎的医生.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习1/最受欢迎的医生.cpp -------------------------------------------------------------------------------- /第一阶段编程练习2/最小最大数之差.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习2/最小最大数之差.cpp -------------------------------------------------------------------------------- /第一阶段编程练习2/石头剪子布.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习2/石头剪子布.cpp -------------------------------------------------------------------------------- /第一阶段编程练习2/计算abc的值.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习2/计算abc的值.cpp -------------------------------------------------------------------------------- /第一阶段编程练习3/哥德巴赫猜想.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习3/哥德巴赫猜想.cpp -------------------------------------------------------------------------------- /第一阶段编程练习3/骑车与走路.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习3/骑车与走路.cpp -------------------------------------------------------------------------------- /第一阶段编程练习4/判断四边形.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习4/判断四边形.cpp -------------------------------------------------------------------------------- /第一阶段编程练习4/找到不一样的数.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习4/找到不一样的数.cpp -------------------------------------------------------------------------------- /第一阶段编程练习4/牛顿迭代方法.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习4/牛顿迭代方法.cpp -------------------------------------------------------------------------------- /第三阶段编程练习1/回文数判断.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第三阶段编程练习1/回文数判断.cpp -------------------------------------------------------------------------------- /第三阶段编程练习1/孙悟空找师傅.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第三阶段编程练习1/孙悟空找师傅.cpp -------------------------------------------------------------------------------- /第三阶段编程练习1/最小公倍数.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第三阶段编程练习1/最小公倍数.cpp -------------------------------------------------------------------------------- /第三阶段编程练习2/取石子游戏.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第三阶段编程练习2/取石子游戏.cpp -------------------------------------------------------------------------------- /第三阶段编程练习2/后缀表达式.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第三阶段编程练习2/后缀表达式.cpp -------------------------------------------------------------------------------- /第三阶段编程练习2/字符串p型编码.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第三阶段编程练习2/字符串p型编码.cpp -------------------------------------------------------------------------------- /第三阶段编程练习2/查看菌落数目.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第三阶段编程练习2/查看菌落数目.cpp -------------------------------------------------------------------------------- /第三阶段编程练习2/猴子分苹果.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第三阶段编程练习2/猴子分苹果.cpp -------------------------------------------------------------------------------- /第二次模拟考试/1020跳格问题.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二次模拟考试/1020跳格问题.cpp -------------------------------------------------------------------------------- /第二次模拟考试/487-3279.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二次模拟考试/487-3279.cpp -------------------------------------------------------------------------------- /第二次模拟考试/五子棋判断输赢.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二次模拟考试/五子棋判断输赢.cpp -------------------------------------------------------------------------------- /第二次模拟考试/区间合并20版本.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二次模拟考试/区间合并20版本.cpp -------------------------------------------------------------------------------- /第二阶段编程练习1/招聘会人数.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习1/招聘会人数.cpp -------------------------------------------------------------------------------- /第二阶段编程练习1/校门外的树.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习1/校门外的树.cpp -------------------------------------------------------------------------------- /第二阶段编程练习1/求特殊自然数.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习1/求特殊自然数.cpp -------------------------------------------------------------------------------- /第二阶段编程练习2/二进制加法.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习2/二进制加法.cpp -------------------------------------------------------------------------------- /第二阶段编程练习2/计算数据的方差.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习2/计算数据的方差.cpp -------------------------------------------------------------------------------- /第二阶段编程练习4/五户共井问题.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习4/五户共井问题.cpp -------------------------------------------------------------------------------- /第二阶段编程练习4/密切数判断.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习4/密切数判断.cpp -------------------------------------------------------------------------------- /第二阶段编程练习4/根据日期求星期.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习4/根据日期求星期.cpp -------------------------------------------------------------------------------- /第二阶段编程练习5/佩奇的勇气机.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习5/佩奇的勇气机.cpp -------------------------------------------------------------------------------- /第二阶段编程练习5/变幻的矩阵.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习5/变幻的矩阵.cpp -------------------------------------------------------------------------------- /第二阶段编程练习5/垂直直方图.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习5/垂直直方图.cpp -------------------------------------------------------------------------------- /第二阶段编程练习5/字符串最大跨距.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习5/字符串最大跨距.cpp -------------------------------------------------------------------------------- /试手练习/ab problem.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/试手练习/ab problem.cpp -------------------------------------------------------------------------------- /2020年期中考试题/小于当前数的数.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2020年期中考试题/小于当前数的数.cpp -------------------------------------------------------------------------------- /2021年期中考试题/操作数列_BST.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2021年期中考试题/操作数列_BST.cpp -------------------------------------------------------------------------------- /2021年期中考试题/爱读书的Tim.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2021年期中考试题/爱读书的Tim.cpp -------------------------------------------------------------------------------- /期中考试/判断是否为C语言的合法标识符.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/期中考试/判断是否为C语言的合法标识符.cpp -------------------------------------------------------------------------------- /第一阶段编程练习1/点和正方形的关系.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习1/点和正方形的关系.cpp -------------------------------------------------------------------------------- /第一阶段编程练习1/能被357整除的数.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习1/能被357整除的数.cpp -------------------------------------------------------------------------------- /第一阶段编程练习3/分离整数的各个数位.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习3/分离整数的各个数位.cpp -------------------------------------------------------------------------------- /第一阶段编程练习4/一种等价类划分问题.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习4/一种等价类划分问题.cpp -------------------------------------------------------------------------------- /第一阶段编程练习4/三个三位数的关系.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习4/三个三位数的关系.cpp -------------------------------------------------------------------------------- /第二阶段编程练习2/二维数组回形遍历.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习2/二维数组回形遍历.cpp -------------------------------------------------------------------------------- /第二阶段编程练习2/统计字母和数字个数.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习2/统计字母和数字个数.cpp -------------------------------------------------------------------------------- /第二阶段编程练习3/寻找平面上的极大点.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习3/寻找平面上的极大点.cpp -------------------------------------------------------------------------------- /第二阶段编程练习4/侃侃而谈的四位朋友.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习4/侃侃而谈的四位朋友.cpp -------------------------------------------------------------------------------- /第二阶段编程练习5/简单的缩略语判断.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习5/简单的缩略语判断.cpp -------------------------------------------------------------------------------- /第一阶段编程练习2/不与最大数相同的数字之和.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习2/不与最大数相同的数字之和.cpp -------------------------------------------------------------------------------- /第一阶段编程练习3/统计满足条件的4位数个数.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第一阶段编程练习3/统计满足条件的4位数个数.cpp -------------------------------------------------------------------------------- /第三阶段编程练习2/计算x的n阶勒让德多项式.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第三阶段编程练习2/计算x的n阶勒让德多项式.cpp -------------------------------------------------------------------------------- /第二阶段编程练习2/计算两个日期之间的天数.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习2/计算两个日期之间的天数.cpp -------------------------------------------------------------------------------- /第二阶段编程练习3/判断字符串是否为回文.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习3/判断字符串是否为回文.cpp -------------------------------------------------------------------------------- /第二阶段编程练习3/提取数字串按数值排序.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习3/提取数字串按数值排序.cpp -------------------------------------------------------------------------------- /第二阶段编程练习4/将两个排序后的数组合并.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/第二阶段编程练习4/将两个排序后的数组合并.cpp -------------------------------------------------------------------------------- /2021年期中考试题/操作数列_MinHeap.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LC-John/IntroductionToComputationHomework2022/HEAD/2021年期中考试题/操作数列_MinHeap.cpp -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compilation & Executable 2 | *.exe 3 | *.o 4 | 5 | # Test cases 6 | *.in 7 | *.out 8 | 9 | # Excel tables 10 | *.xls 11 | *.xlsx 12 | *.docx 13 | *.pdf -------------------------------------------------------------------------------- /2021年期末考试题/购买纪念品.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 北京大学邀请了一些专家,现在交给你一个任务,到纪念品商店里购买纪念品。已知一份纪念品的价 5 | 格是 1 元 9 角,而班主任给你的钱是 a 元 b 角,问,你最多能买多少纪念品呢? 6 | 7 | 关于输入 8 | 9 | 输入格式:输入只有一行两个整数,分别表示 a 和 b,空格间隔。 10 | 11 | 关于输出 12 | 13 | 输出格式:输出一行一个整数,表示你最多能买多少个纪念品。 14 | 15 | 例子输入 16 | 17 | 10 3 18 | 19 | 例子输出 20 | 21 | 5 22 | 23 | 提示信息 24 | 25 | 对于全部的测试点,保证 0 <= a <= 10000 , 0 <= b <= 9 26 | *****/ 27 | 28 | #include 29 | using namespace std; 30 | 31 | #define PRICE 19 32 | 33 | int main() 34 | { 35 | int a = 0, b = 0; 36 | cin >> a >> b; 37 | cout << (a * 10 + b) / PRICE << endl; 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /2020年期末考试题/最长连号.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 输入n个正整数,(1<=n<=10000),要求输出最长的连号的长度。(连号指从小到大连续自然数) 5 | 6 | 关于输入 7 | 8 | 第一行,一个数n; 第二行,n个正整数,之间用空格隔开。 9 | 10 | 关于输出 11 | 12 | 一个数,最长连号中数的个数。 13 | 14 | 例子输入 15 | 16 | 10 17 | 3 5 6 2 3 4 5 6 8 9 18 | 19 | 例子输出 20 | 21 | 5 22 | 23 | 提示信息 24 | 25 | 例子输入中,最长连号是 2 3 4 5 6,其中有5个数。 26 | *****/ 27 | 28 | #include 29 | using namespace std; 30 | 31 | #define MIN_INT 0x80000000 32 | 33 | int main() 34 | { 35 | int n = 0, prev = MIN_INT, num = 0, cnt = 0, max_cnt = 0; 36 | cin >> n; 37 | while (n--) 38 | { 39 | cin >> num; 40 | if (num - 1 == prev) 41 | cnt++; 42 | else 43 | { 44 | if (cnt > max_cnt) 45 | max_cnt = cnt; 46 | cnt = 1; 47 | } 48 | prev = num; 49 | } 50 | if (cnt > max_cnt) 51 | max_cnt = cnt; 52 | cout << max_cnt << endl; 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /试手练习/放苹果问题.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法 5 | (用K表示)?注意:5,1,1和1,5,1是同一种分发。 6 | 7 | 关于输入 8 | 9 | 第一行是测试数据的数目t(0<= t <= 20),其后的t行均包含两个整数M和N,以空格分开。 10 | 1<= M <= 25; 11 | 1<= N <= 10; 12 | 13 | 关于输出 14 | 15 | 对输入的每组数据M和N,用一行输出相应的K 16 | 17 | 例子输入 18 | 19 | 1 20 | 7 3 21 | 22 | 例子输出 23 | 24 | 8 25 | 26 | 提示信息 27 | 28 | 采用递归思想解题。 29 | *****/ 30 | 31 | #include 32 | using namespace std; 33 | 34 | int dfs(int apple, int plate) 35 | { 36 | if (plate == 1) 37 | return 1; 38 | if (!apple) 39 | return 1; 40 | if (apple >= plate) 41 | return dfs(apple - plate, plate) + dfs(apple, plate - 1); 42 | return dfs(apple, apple); 43 | } 44 | 45 | int main() 46 | { 47 | int t = 0, apple = 0, plate = 0; 48 | cin >> t; 49 | while(t--) 50 | { 51 | cin >> apple >> plate; 52 | cout << dfs(apple, plate) << endl; 53 | } 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /第三阶段编程练习3/二叉树.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 如上图所示,由正整数1, 2, 3, ...组成了一棵无限大的二叉树。从某一个结点到根结点(编号是1的结点)都有一条 5 | 唯一的路径,比如从10到根结点的路径是(10, 5, 2, 1),从4到根结点的路径是(4, 2, 1),从根结点1到根结点的路 6 | 径上只包含一个结点1,因此路径就是(1)。对于两个结点x和y,假设他们到根结点的路径分别是(x1, x2, ... ,1)和 7 | (y1, y2, ... ,1)(这里显然有x = x1,y = y1),那么必然存在两个正整数i和j,使得从xi 和 yj开始,有 8 | xi = yj , xi + 1 = yj + 1, xi + 2 = yj + 2,... 现在的问题就是,给定x和y,要求xi(也就是yj)。 9 | 10 | 关于输入 11 | 12 | 输入只有一行,包括两个正整数x和y,这两个正整数都不大于1000。 13 | 14 | 关于输出 15 | 16 | 输出只有一个正整数xi。 17 | 18 | 例子输入 19 | 20 | 10 4 21 | 22 | 例子输出 23 | 24 | 2 25 | *****/ 26 | 27 | #include 28 | using namespace std; 29 | 30 | /** 31 | 思路 32 | 33 | 简单观察,便可以发现,对于任意一个节点i,它的父节点总是i / 2(int类型下)。 34 | 那么我们不断去让a和b中较大的节点向上走到其父节点,直到a与b重合即可。 35 | **/ 36 | 37 | int main() 38 | { 39 | int a = 0, b = 0; 40 | cin >> a >> b; 41 | while (a != b) 42 | if (a > b) 43 | a /= 2; 44 | else 45 | b /= 2; 46 | cout << a << endl; 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /综合练习/最小公倍数.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 输入两个数,输出其最小公倍数。 5 | 6 | 关于输入 7 | 8 | 输入两个数(100以内),用逗号隔开。 9 | 10 | 关于输出 11 | 12 | 输出它们的最小公倍数。 13 | 14 | 例子输入 15 | 16 | 12,45 17 | 18 | 例子输出 19 | 20 | 180 21 | 22 | 提示信息 23 | 24 | 先用辗转相除法求出最大公约数,然后求得公倍数。注意此题输入是用逗号隔开而不是用空格隔开。 25 | 辗转相除法:设两数为a、b(a>b),求a和b最大公约数(a,b)的步骤如下:用b除a,得a=bq......r1(0≤r1)。 26 | 若r1=0,则(a,b)=b;若r1≠0,则再用r1除b,得b=r1q......r2 (0≤r2).若r2=0,则(a,b)=r1,若r2≠0, 27 | 则继续用r2除r1,……如此下去,直到能整除为止。其最后一个非零除数即为(a,b) 28 | *****/ 29 | 30 | #include 31 | using namespace std; 32 | 33 | int gcd(int a, int b) 34 | { 35 | int t = 0; 36 | while (b) 37 | { 38 | t = a % b; 39 | a = b; 40 | b = t; 41 | } 42 | return a; 43 | } 44 | 45 | int main() 46 | { 47 | int a = 0, b = 0; 48 | char c = '\0'; 49 | cin >> a >> c >> b; 50 | if (b > a) 51 | { 52 | a ^= b; 53 | b ^= a; 54 | a ^= b; 55 | } 56 | 57 | cout << a * b / gcd(a, b) << endl; 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /2020年期末考试题/括号配对.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 小凡同学在学习C语言时无意间发现括号的配对是件很有意思的事。对于不同数量的括号, 5 | 似乎有很多种不同但是合法的组合方式。对于小凡给出的括号总对数N,你能告诉他总共 6 | 有多少种不同的括号组合方式吗? 7 | 8 | 关于输入 9 | 10 | 输入有一行,为括号的总对数N,N为不超过10的正整数。 11 | 12 | 关于输出 13 | 14 | 按左括号优先的顺序排列出所有合法的组合方式。 15 | 16 | 例子输入 17 | 18 | 3 19 | 20 | 例子输出 21 | 22 | ((())) 23 | (()()) 24 | (())() 25 | ()(()) 26 | ()()() 27 | *****/ 28 | 29 | #include 30 | using namespace std; 31 | 32 | #define MAX_LEN 100 33 | 34 | void dfs(int cnt, int n, char *cur, int l) 35 | { 36 | if (!n && !cnt) 37 | { 38 | cout << cur << endl; 39 | return; 40 | } 41 | if (cnt < n) 42 | { 43 | cur[l] = '('; 44 | dfs(cnt + 1, n, cur, l + 1); 45 | cur[l] = '\0'; 46 | } 47 | if (cnt) 48 | { 49 | cur[l] = ')'; 50 | dfs(cnt - 1, n - 1, cur, l + 1); 51 | cur[l] = '\0'; 52 | } 53 | } 54 | 55 | int main() 56 | { 57 | int n = 0; 58 | char cur[MAX_LEN] = ""; 59 | cin >> n; 60 | dfs(0, n, cur, 0); 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /试手练习/前缀表达式.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 前缀表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的前缀表示法为+ 2 3。 5 | 前缀表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) * 4 6 | 的前缀表示法为* + 2 3 4。本题求解前缀表达式的值,其中运算符包括+ - * /四个。 7 | 8 | 关于输入 9 | 10 | 输入为一行,其中运算符和运算数之间都用空格分隔,运算数是浮点数。 11 | 12 | 关于输出 13 | 14 | 输出为一行,表达式的值。 15 | 可直接用printf("%f\n", v)输出表达式的值v。 16 | 17 | 例子输入 18 | 19 | * + 11.0 12.0 + 24.0 35.0 20 | 21 | 例子输出 22 | 23 | 1357.000000 24 | 25 | 提示信息 26 | 27 | 可使用atof(str)把字符串转换为一个double类型的浮点数。atof定义在stdlib.h中。 28 | 此题可使用函数递归调用的方法求解。 29 | *****/ 30 | 31 | #include 32 | 33 | #define MAX_LEN 100 34 | char buf[MAX_LEN] = ""; 35 | 36 | double dfs() 37 | { 38 | double n = 0; 39 | scanf("%s", buf); 40 | switch(buf[0]) 41 | { 42 | case '+': return dfs() + dfs(); 43 | case '-': return dfs() - dfs(); 44 | case '*': return dfs() * dfs(); 45 | case '/': return dfs() / dfs(); 46 | default: 47 | sscanf(buf, "%lf", &n); 48 | return n; 49 | } 50 | return n; 51 | } 52 | 53 | int main() 54 | { 55 | printf("%lf\n", dfs()); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /第四阶段编程练习1/计算2的N次方.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 任意给定一个正整数N(N<=100),计算2的N次方的值。 5 | 6 | 关于输入 7 | 8 | 输入只有一个正整数N。 9 | 10 | 关于输出 11 | 12 | 输出2的N次方的值。 13 | 14 | 例子输入 15 | 16 | 5 17 | 18 | 例子输出 19 | 20 | 32 21 | *****/ 22 | 23 | #include 24 | #include 25 | #include 26 | using namespace std; 27 | 28 | #define MAX_LEN 500 29 | char *a = NULL, *b = NULL; 30 | 31 | void add() 32 | { 33 | int c = 0; 34 | reverse(a, a + strlen(a)); 35 | memset(b, 0x00, MAX_LEN * sizeof(char)); 36 | strcpy(b, a); 37 | for (int i = 0; a[i] != '\0'; i++) 38 | { 39 | a[i] = a[i] - '0' + b[i] - '0' + c; 40 | c = a[i] / 10; 41 | a[i] = '0' + (a[i] % 10); 42 | } 43 | if (c) 44 | a[strlen(a)] = '0' + c; 45 | reverse(a, a + strlen(a)); 46 | } 47 | 48 | int main() 49 | { 50 | int n = 0; 51 | a = new char[MAX_LEN]; 52 | b = new char[MAX_LEN]; 53 | cin >> n; 54 | memset(a, 0x00, MAX_LEN * sizeof(char)); 55 | a[0] = '1'; 56 | while (n--) 57 | add(); 58 | cout << a; 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /第三阶段编程练习3/分解因数.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 给出一个正整数a,要求分解成若干个正整数的乘积,即a = a1 * a2 * a3 * ... * an,并且 5 | 1 < a1 <= a2 <= a3 <= ... <= an,问这样的分解的种数有多少。注意到a = a也是一种分解。 6 | 7 | 关于输入 8 | 9 | 第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数a (1 < a < 32768) 10 | 11 | 关于输出 12 | 13 | n行,每行输出对应一个输入。输出应是一个正整数,指明满足要求的分解的种数 14 | 15 | 例子输入 16 | 17 | 2 18 | 2 19 | 20 20 | 21 | 例子输出 22 | 23 | 1 24 | 4 25 | *****/ 26 | 27 | #include 28 | #include 29 | using namespace std; 30 | 31 | int ans = 1; // 搜索结果,初始化为1(即只有这个数本身) 32 | 33 | /** 深度优先搜索 **/ 34 | void dfs(int a, int curr) // a为当前数字,curr为搜索到可能的因数 35 | { 36 | if (curr * curr > a) // 若curr的平方大于a 37 | return; // 则curr不可能是a的因数,返回 38 | int sq = sqrt(a); // sq为a可能的因数的上界 39 | for(int i = curr; i <= sq; i++) 40 | if (a % i == 0) // 当i是a的因数时 41 | { 42 | ans++; // 多出一种可能的分解方式,ans加1 43 | dfs(a / i, i); // 向下递归搜索 44 | } 45 | } 46 | 47 | int main() 48 | { 49 | int n = 0, num = 0; 50 | cin >> n; 51 | while (n--) 52 | { 53 | ans = 1; 54 | cin >> num; 55 | dfs(num, 2); 56 | cout << ans << endl; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Zhang Huangzhao 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /期末考试/阶梯电价购电.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 为了提高能源效率,北京市对居民用电实行阶梯式递增电价,第一档为0~240度(含), 5 | 每度电为0.4883元,第二档为241~400度(含),每度电为0.5383元;第三档为400度以 6 | 上,每度电为0.7883元。阶梯电价的含义是,如果本月用电量是246度,那么其中240度 7 | 执行第一档的价格0.4883×240,超过240度的部分还有6度,执行第二档价格0.5383×6, 8 | 实际电费为两档电费的总和。 9 | 输入为一个整数,为持有的人民币m,以元为单位。若这m元全部用来购电,求本月可购买 10 | 的用电度数d,保留到小数点后两位。 11 | 12 | 关于输入 13 | 14 | 输入为一个整数,为持有的人民币m,以元为单位。 15 | 16 | 关于输出 17 | 18 | 本月可购买的用电度数d,保留到小数点后两位。 19 | 20 | 例子输入 21 | 22 | 100 23 | 24 | 例子输出 25 | 26 | 204.79 27 | 28 | 提示信息 29 | 30 | 以double类型定义可购买电的度数. setprecision 需 include iomanip 31 | *****/ 32 | 33 | #include 34 | #include 35 | using namespace std; 36 | 37 | #define PRICE1 0.4883 38 | #define PRICE2 0.5383 39 | #define PRICE3 0.7883 40 | #define TH1 (240 * 0.4883) 41 | #define TH2 (160 * 0.5383) 42 | #define VOL1 240 43 | #define VOL2 400 44 | 45 | int main() 46 | { 47 | double m; 48 | cin >> m; 49 | if (m <= TH1) 50 | cout << setprecision(2) << fixed << m / PRICE1; 51 | else if (m <= TH1 + TH2) 52 | cout << setprecision(2) << fixed << (m - TH1) / PRICE2 + VOL1; 53 | else 54 | cout << setprecision(2) << fixed << (m - TH1 - TH2) / PRICE3 + VOL2; 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /第四阶段编程练习1/寻找最长公共前缀.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 请从4个字符串中找出最长的公共前缀。 5 | 6 | 关于输入 7 | 8 | 输入有4行。每行输入是一个字符串(可能包含空格),长度不超过255个字符。 9 | 10 | 关于输出 11 | 12 | 所有输入字符串的公共前缀。如果没有公共前缀,则程序不输出内容。 13 | 14 | 例子输入 15 | 16 | Asdfcsdk 17 | Asddf 18 | Asdtes 19 | Asdtexd 20 | 21 | 例子输出 22 | 23 | Asd 24 | *****/ 25 | 26 | #include 27 | #include 28 | #include 29 | using namespace std; 30 | 31 | #define MAX_L 300 32 | #define N 4 33 | 34 | char s[N][MAX_L] = {"\0"}; 35 | int l = MAX_L; 36 | 37 | int main() 38 | { 39 | bool flag = true; 40 | for (int i = 0; i < N; i++) 41 | { 42 | cin.getline(s[i], MAX_L); 43 | l = min(l, (int)strlen(s[i])); 44 | } 45 | for (int i = l; i > 0; i--) 46 | { 47 | flag = true; 48 | for (int j = 1; j < N; j++) 49 | if (strncmp(s[j], s[j - 1], i)) 50 | { 51 | flag = false; 52 | break; 53 | } 54 | if (flag) 55 | { 56 | for (int j = 0; j < i; j++) 57 | cout << s[0][j]; 58 | cout << endl; 59 | return 0; 60 | } 61 | } 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /期末考试/世界杯赢家.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 卡塔尔世界杯正在举行!假设有 n 场比赛,每场比赛均分出胜负,没有平局,请找出所有没有输掉任何比赛, 5 | 且至少参加了一场比赛的国家,并按国家编号递增输出;若不存在这样的国家,输出字符串"None"。 6 | 7 | 关于输入 8 | 9 | 第一行是一个正整数 n,表示比赛场数(1 <= n <= 100000)。 10 | 接下来 n 行,每行两个正整数,分别表示该场比赛获胜和失利的国家的编号(1 <= 国家编号 <= 100000), 11 | 第一个为获胜国家编号,第二个为失利国家编号。 12 | 13 | 关于输出 14 | 15 | 一列正整数,所有没有输掉任何比赛的国家编号,但不包括那些没有参与过任何一场比赛的国家。国家间使用 16 | ", "(一个逗号和一个空格)作为分隔;或者"None"。 17 | 18 | 例子输入 19 | 20 | 4 21 | 2 3 22 | 1 3 23 | 4 2 24 | 6 4 25 | 26 | 例子输出 27 | 28 | 1, 6 29 | 30 | 提示信息 31 | 32 | 只需考虑那些参与至少一场比赛的国家。测试用例保证不存在两场比赛结果相同。 33 | *****/ 34 | 35 | #include 36 | using namespace std; 37 | 38 | #define MAXN 100100 39 | #define EMPTY 0 40 | #define YES 1 41 | #define NO 2 42 | 43 | int f[MAXN] = {0}; 44 | 45 | int main() 46 | { 47 | int n = 0, a = 0, b = 0; 48 | bool flag = true; 49 | cin >> n; 50 | while (n--) 51 | { 52 | cin >> a >> b; 53 | f[a] = (f[a] == NO) ? f[a] : YES; 54 | f[b] = NO; 55 | } 56 | for (int i = 0; i < MAXN; i++) 57 | if (f[i] == YES) 58 | { 59 | if (flag) 60 | flag = false; 61 | else 62 | cout << ", "; 63 | cout << i; 64 | } 65 | if (flag) 66 | cout << "None"; 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /2020年期末考试题/求到最大最小值距离差最小的数.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 给定一组正整数,其中的最大值和最小值分别为max和min,其中的 5 | 一个数x到max和min的距离差D定义为 6 | abs(abs(x-max) - abs(x-min))。 7 | 其中,abs()表示求一个数的绝对值 8 | 9 | 关于输入 10 | 11 | 输入第一行为整数n,剩余n行每行一个正整数。(n<=10000) 12 | 13 | 关于输出 14 | 15 | 输出仅一行,它的值为使得距离差D最小的x。 16 | 17 | 例子输入 18 | 19 | 5 20 | 3 21 | 1 22 | 7 23 | 5 24 | 9 25 | 26 | 例子输出 27 | 28 | 5 29 | 30 | 提示信息 31 | 32 | 函数abs()定义在stdlib.h中。 33 | *****/ 34 | 35 | #include 36 | #include 37 | using namespace std; 38 | 39 | #define MAX_N 10100 40 | #define MAX_INT 0x7fffffff 41 | #define MIN_INT 0x80000000 42 | 43 | int v[MAX_N] = {0}; 44 | 45 | int calc_d(int x, int max_v, int min_v) 46 | { 47 | return abs(abs(x - max_v) - abs(x - min_v)); 48 | } 49 | 50 | int main() 51 | { 52 | int n = 0, max_v = MIN_INT, min_v = MAX_INT; 53 | int min_d = MAX_INT, ans = 0, d = 0; 54 | cin >> n; 55 | for (int i = 0; i < n; i++) 56 | { 57 | cin >> v[i]; 58 | max_v = max(max_v, v[i]); 59 | min_v = min(min_v, v[i]); 60 | } 61 | for (int i = 0; i < n; i++) 62 | { 63 | d = calc_d(v[i], max_v, min_v); 64 | if (d < min_d) 65 | { 66 | ans = v[i]; 67 | min_d = d; 68 | } 69 | } 70 | cout << ans << endl; 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /第三阶段编程练习5/插入乘号.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 给定一个非负整数,用k个乘号将其分割,使得乘积最大。 5 | 例如:在整数12345中插入两个乘号,有以下插入法: 6 | 1*2*345 1*23*45 1*234*5 7 | 12*3*45 12*34*5 8 | 123*4*5 9 | 其中最大值是123*4*5 = 2460 10 | 11 | 关于输入 12 | 13 | 一行两个非负整数,非负整数s(s ≦ 10^9)和乘号的个数k(0 ≦ k < s的位数)。 14 | 输入保证,如果按题目要求的乘法操作,不会使int发生溢出。 15 | 16 | 关于输出 17 | 18 | 一行一个整数,即乘积的最大值 19 | 20 | 例子输入 21 | 22 | 12345 2 23 | 24 | 例子输出 25 | 26 | 2460 27 | *****/ 28 | 29 | #include 30 | #include 31 | #include 32 | using namespace std; 33 | 34 | #define MAX_LEN 20 35 | 36 | int dfs(char *str, int l, int k) // str字符串,长度l,乘号个数k 37 | { 38 | int num = 0, ret = 0; 39 | if (l <= k) // 若乘号个数大于间隙数 40 | return -1; // 则不可能完成插入,直接终止,返回-1 41 | if (!k) // 若没有乘号 42 | { 43 | sscanf(str, "%d", &num); // 则返回当前字符串对应的数字 44 | return num; 45 | } 46 | for (int i = 1; i < l; i++) // 从第一个空隙开始 47 | { 48 | num = num * 10 + str[i - 1] - '0'; 49 | ret = max(ret, num * dfs(str + i, l - i, k - 1)); // 插入乘号,递归搜索 50 | } 51 | return ret; 52 | } 53 | 54 | int main() 55 | { 56 | char str[MAX_LEN] = "\0"; 57 | int l = 0, k = 0; 58 | scanf("%s %d", str, &k); 59 | l = strlen(str); 60 | printf("%d\n", dfs(str, l, k)); 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /2021年期末考试题/发水果.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 中午是幼儿园水果时间,老师会给每个小朋友发水果。教室为一个矩形区域,共有N 排, 5 | 每排M个工位。老师通常按照逆时针方向螺旋发水果。已知每个座位有一个数字,表示该 6 | 小朋友的学号,每个学号各不相同。已知老师从(0, 0)位置开始,按照逆时针螺旋的 7 | 顺序发水果,请输出收到水果的小朋友的学号序列。 8 | 9 | 关于输入 10 | 11 | 第一行 两个数, 数组行列 N,M 12 | 接下来 N 行,每行 M 个正整数,表示每个位置的员工工号 13 | 1 ≤ N ≤ 15 14 | 1 ≤ M ≤ 15 15 | 16 | 关于输出 17 | 18 | 发放水果学号序列 19 | 20 | 例子输入 21 | 22 | 3 3 23 | 1 2 3 24 | 4 5 6 25 | 7 8 9 26 | 27 | 例子输出 28 | 29 | 1 4 7 8 9 6 3 2 5 30 | *****/ 31 | 32 | #include 33 | #include 34 | using namespace std; 35 | 36 | #define MAX_N 20 37 | #define ND 4 38 | 39 | int n_row = 0, n_col = 0; 40 | int arr[MAX_N][MAX_N] = {0}; 41 | const int dr[ND] = {1, 0, -1, 0}, dc[ND] = {0, 1, 0, -1}; 42 | 43 | int main() 44 | { 45 | int r = 1, c = 1, cnt = 0, d = 0; 46 | memset(arr, 0xff, sizeof(arr)); 47 | cin >> n_row >> n_col; 48 | for (int i = 1; i <= n_row; i++) 49 | for (int j = 1; j <= n_col; j++) 50 | cin >> arr[i][j]; 51 | while (cnt < n_row * n_col) 52 | { 53 | if (cnt) 54 | cout << " "; 55 | cout << arr[r][c]; 56 | arr[r][c] = -1; 57 | cnt++; 58 | if (arr[r + dr[d]][c + dc[d]] < 0) 59 | d = (d + 1) % ND; 60 | r = r + dr[d]; 61 | c = c + dc[d]; 62 | } 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /第三阶段编程练习3/集合里的乘法.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 给定整数集合S和一个目标数T,判断是否可以从S中挑选一个非空子集,子集中的数相乘的乘积为T。 5 | 6 | 关于输入 7 | 8 | 输入为两行。 9 | 第一行为目标数T和S中的元素个数N,以空格隔开。 10 | 第二行为S中的N个元素,以空格隔开。 11 | 其中 N <= 16。 12 | 13 | 关于输出 14 | 15 | 如果可以,则输出YES,否则输出NO。 16 | 17 | 例子输入 18 | 19 | Sample Input 1: 20 | 12 5 21 | 1 2 3 4 5 22 | 23 | Sample Input 2: 24 | 33 5 25 | 4 2 8 7 5 26 | 27 | 例子输出 28 | 29 | Sample Output 1: 30 | YES 31 | 32 | Sample Output 2: 33 | NO 34 | *****/ 35 | 36 | #include 37 | using namespace std; 38 | 39 | #define MAX_N 100 40 | 41 | int s[MAX_N] = {}, n = 0; 42 | 43 | /** 深度优先搜索 **/ 44 | bool dfs(int t, int depth) // t为目标乘积,depth为搜索深度 45 | { 46 | if (t == 1) // t为1,说明目标已经达成 47 | return true; // 返回true 48 | if (depth >= n) // depth超过n,说明目标无法达成 49 | return false; // 返回false 50 | if (dfs(t, depth + 1)) // 不用s[depth]来达成目标 51 | return true; 52 | if (s[depth] && !(t % s[depth]) && dfs(t / s[depth], depth + 1)) // 用s[depth]来达成目标,需要考虑0的情况 53 | return true; 54 | return false; 55 | } 56 | 57 | int main() 58 | { 59 | int t = 0; 60 | cin >> t >> n; 61 | for (int i = 0; i < n; i++) 62 | cin >> s[i]; 63 | if (dfs(t, 0)) 64 | cout << "YES" << endl; 65 | else 66 | cout << "NO" << endl; 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /期末考试/佳佳的筷子.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 佳佳与常人不同,吃饭用三只筷子,两根短的加一根比较长的。两只短的筷子的长度应该尽可能接近, 5 | 但是最长的那根长度是无所谓的。如果一套筷子的长度分别是a,b,c(a<=b<=c),则用(a-b)*(a-b)的值 6 | 表示这套筷子的质量,这个值越小,这套筷子的质量越高。 7 | 佳佳请朋友吃饭,并准备为每人准备一套这种特殊的筷子。佳佳有n(n<=5000)只筷子,他希望找到一种 8 | 办法搭配好k套筷子,使得这些筷子的质量之和最小。 9 | 10 | 关于输入 11 | 12 | 第一行是两个整数n和k(n<=5000,3*k<=n) 13 | 第二行是n个整数表示筷子的长度 14 | 15 | 关于输出 16 | 17 | 输出一个整数,表示筷子质量和的最小值 18 | 19 | 例子输入 20 | 21 | 5 1 22 | 1 3 4 7 10 23 | 24 | 例子输出 25 | 26 | 1 27 | 28 | 提示信息 29 | 30 | 从小到大排序后从后向前递推 31 | *****/ 32 | 33 | #include 34 | #include 35 | using namespace std; 36 | 37 | #define MAX_N 5010 38 | #define MAX_INT 0x7fffffff 39 | 40 | int l[MAX_N] = {0}, dp[MAX_N][MAX_N] = {0}; 41 | 42 | int main() 43 | { 44 | int n = 0, k = 0; 45 | cin >> n >> k; 46 | for (int i = 1; i <= n; i++) 47 | cin >> l[i]; 48 | sort(l + 1, l + n + 1); 49 | for (int i = 0; i <= n; i++) 50 | for (int j = 0; j <= n; j++) 51 | dp[i][j] = MAX_INT; 52 | for (int i = 1; i <= n; i++) 53 | dp[0][i] = 0; 54 | for (int i = 1; i <= k; i++) 55 | for (int j = n - 3 * i + 1; j; j--) 56 | dp[i][j] = min((l[j + 1] - l[j]) * (l[j + 1] - l[j]) + dp[i - 1][j + 2], 57 | dp[i][j + 1]); 58 | cout << dp[k][1] << endl; 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /第四阶段编程练习1/购买礼物.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 要过新年了,小明想给许多同学购买礼物,选好礼物结账时发现带的钱不够,所以只能选择留下一部分。 5 | 每个要送礼物的同学在他心中有个优先级,小明决定优先级最大的优先购买,他为每个人挑选的礼物价格 6 | 不同,下面请你算出小明能给多少人买到礼物。 7 | 8 | 关于输入 9 | 10 | 输入有N+1行,第一行两个数字,选的礼物总数N和带的钱的总数M,后面N行每行包含两个数字,第一个数 11 | 字表示礼物的价格P,第二个数字表示这个礼物要送的人在他心中的优先级L,越大越优先购买,优先级不 12 | 能相同(N<100 M<1000 P<100 L<200 N,M,P,L均为整数) 13 | 14 | 关于输出 15 | 16 | 输出一行,能买的礼物个数 17 | 18 | 例子输入 19 | 20 | 5 10 21 | 2 4 22 | 6 3 23 | 1 5 24 | 7 2 25 | 1 1 26 | 27 | 例子输出 28 | 29 | 3 30 | 31 | 提示信息 32 | 33 | 若优先级最高的礼物价格超出带的钱总数,视为不能购买任何礼物(优先级较高的人没有,则不会考虑给 34 | 优先级低的买) 35 | *****/ 36 | 37 | #include 38 | #include 39 | using namespace std; 40 | 41 | #define MAX_N 110 42 | 43 | struct Gift 44 | { 45 | int pri; // 优先级 46 | int val; // 价值 47 | } g[MAX_N] = {{0, 0}}; 48 | 49 | bool cmp(const Gift& a, const Gift& b) 50 | { 51 | return a.pri > b.pri; 52 | } 53 | 54 | int main() 55 | { 56 | int n = 0, m = 0, ans = 0; 57 | cin >> n >> m; 58 | for (int i = 0; i < n; i++) 59 | cin >> g[i].val >> g[i].pri; 60 | sort(g, g + n, cmp); 61 | for (int i = 0; i < n; i++) 62 | if (g[i].val <= m) 63 | { 64 | ans++; 65 | m -= g[i].val; 66 | } 67 | else 68 | break; 69 | cout << ans << endl; 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /第三阶段编程练习4/分割乘积.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 给定一个整数,求插入两个乘号的最大乘积。 5 | 6 | 关于输入 7 | 8 | 只有一行,一个整数。 9 | 10 | 关于输出 11 | 12 | 所求出的最大乘积。 13 | 14 | 例子输入 15 | 16 | 4242 17 | 18 | 例子输出 19 | 20 | 336 21 | 22 | 提示信息 23 | 24 | 整数有正有负。 25 | 输入保证:如果按题目要求的乘法操作,不会使int发生溢出。 26 | *****/ 27 | 28 | #include 29 | #include 30 | 31 | #define MAX_N 30 32 | #define MIN_INT 0x80000000 33 | 34 | int main() 35 | { 36 | char s[MAX_N] = "", s1[MAX_N] = "", s2[MAX_N] = "", s3[MAX_N] = ""; 37 | int len = 0, n1 = 0, n2 = 0, n3 = 0; 38 | int ans = MIN_INT, prod = 0; 39 | int st = 1; 40 | scanf("%s", s); 41 | len = strlen(s); 42 | st += (s[0]=='-'); 43 | for(int i = st; i < len - 1; i++) 44 | for(int j = i + 1; j < len; j++) 45 | { 46 | memset(s1, '\0', sizeof(s1)); 47 | memset(s2, '\0', sizeof(s2)); 48 | memset(s3, '\0', sizeof(s3)); 49 | strncpy(s1, s, i); 50 | strncpy(s2, s + i, j - i); 51 | strcpy(s3, s + j); 52 | sscanf(s1, "%d", &n1); 53 | sscanf(s2, "%d", &n2); 54 | sscanf(s3, "%d", &n3); 55 | prod = n1 * n2 * n3; 56 | if (ans < prod) 57 | ans = prod; 58 | // printf("%d %d %d %d\n", n1, n2, n3, ans); 59 | } 60 | printf("%d\n", ans); 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /期末考试/炸鸡排.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 小P买了n块鸡排,想将它们做成美味的炸鸡排,其中第i块鸡排需要t[i]秒炸熟。小P只有一 5 | 个炸锅,炸锅内可以放置k(k≤n)块鸡排。小P是个完美主义者,他要求任意时刻炸锅内必须 6 | 恰有k块鸡排。他可以在任意时刻改变锅内正在炸的鸡排,只需保证已经熟了的鸡排不能继续 7 | 留在锅中。小P希望知道炸鸡排最多可以持续多少时间。 8 | 例如,小P的三块鸡排需要分别需要1,1,1的时间炸熟,炸锅内需要放置2块鸡排,那么他决定 9 | 在第一个0.5秒炸1和2两块鸡排,第二个0.5秒炸2和3两块鸡排,第三个0.5秒炸1和3两块鸡排, 10 | 共持续了1.5秒。 11 | 12 | 关于输入 13 | 14 | 第一行输入两个正整数n和k,k≤n 15 | 第二行输入n个正整数,代表n块鸡排分别需要炸熟的时间t[1],t[2]...t[n] 16 | 输入数据保证,n≤1000,0<t[i]≤1000000 17 | 18 | 关于输出 19 | 20 | 输出一个双精度浮点数,代表炸鸡排最多可以持续的时间,结果保留三位小数。 21 | 22 | 例子输入 23 | 24 | 4 2 25 | 5 1 1 2 26 | 27 | 例子输出 28 | 29 | 4.000 30 | 31 | 提示信息 32 | 33 | 样例说明: 34 | 第1秒,放置1和2 35 | 第2秒,放置1和3 36 | 第3、4秒,放置1和4 37 | 至此,2,3,4已经全部熟了,无法继续进行 38 | *****/ 39 | 40 | #include 41 | #include 42 | using namespace std; 43 | 44 | #define MAX_N 1010 45 | 46 | int t[MAX_N] = {0}; 47 | 48 | int main() 49 | { 50 | int k = 0, n = 0; 51 | scanf("%d%d", &n, &k); 52 | double sum = 0; 53 | for(int i = 0; i < n; i++) 54 | { 55 | scanf("%d", &(t[i])); 56 | sum += t[i]; 57 | } 58 | sort(t, t + n); 59 | if(t[n - 1] <= sum / k) 60 | printf("%.3lf", sum / k); 61 | else 62 | { 63 | for (int i = n - 1; i >= 0 && sum / k < t[i]; i--) 64 | { 65 | sum -= t[i]; 66 | k--; 67 | } 68 | printf("%.3lf", sum / k); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /综合练习/检查队伍.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 操场上,小明老师要求同学们站成整齐的一排队伍。在小明老师眼中,只有下面这三种 5 | 排队方式才算是整齐的队伍: 6 | 1)从左到右,身高从高到低排列,即h1>=h2>=h3...>=hm;(m为排队人数) 7 | 2)从左到右,身高从低到高排列,即h1<=h2<=h3...<=hm; 8 | 3)从左到右,身高先升高再降低,即h1<=h2<=...<=hi-1<=hi>=hi+1>=...>=hm; 9 | 请你写一段代码来帮小明老师检查一下队伍吧。 10 | 11 | 关于输入 12 | 13 | 第一行一个整数n,表示后面有n种排队方式。接下来有2n行,每个奇数行为一个整数m, 14 | 接下来的一行为m个整数,代表每位同学的身高。1<=n<=10,1<=m<=100。身高的范围 15 | 表示为(0, 100]. 16 | 17 | 关于输出 18 | 19 | 输出共n行。对每种排队方式,如果是整齐的,输出Yes,否则输出No。 20 | 21 | 例子输入 22 | 23 | 5 24 | 1 25 | 50 26 | 3 27 | 6 6 6 28 | 5 29 | 10 30 50 70 90 30 | 6 31 | 65 55 45 50 55 60 32 | 10 33 | 51 52 53 54 55 54 53 52 51 50 34 | 35 | 例子输出 36 | 37 | Yes 38 | Yes 39 | Yes 40 | No 41 | Yes 42 | *****/ 43 | 44 | #include 45 | using namespace std; 46 | 47 | #define MAX_N 110 48 | 49 | int q[MAX_N] = {0}; 50 | int n = 0; 51 | 52 | bool check() 53 | { 54 | int l = 0, r = n - 1; 55 | while (l < r && q[l] <= q[l + 1]) 56 | l++; 57 | while (l < r && q[r - 1] >= q[r]) 58 | r--; 59 | return l == r; 60 | } 61 | 62 | int main() 63 | { 64 | int n_case = 0; 65 | cin >> n_case; 66 | while (n_case--) 67 | { 68 | cin >> n; 69 | for (int i = 0; i < n; i++) 70 | cin >> q[i]; 71 | if (check()) 72 | cout << "Yes" << endl; 73 | else 74 | cout << "No" << endl; 75 | } 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /第四阶段编程练习2/检查队伍.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 操场上,小明老师要求同学们站成整齐的一排队伍。在小明老师眼中,只有下面这三种 5 | 排队方式才算是整齐的队伍: 6 | 1)从左到右,身高从高到低排列,即h1>=h2>=h3...>=hm;(m为排队人数) 7 | 2)从左到右,身高从低到高排列,即h1<=h2<=h3...<=hm; 8 | 3)从左到右,身高先升高再降低,即h1<=h2<=...<=hi-1<=hi>=hi+1>=...>=hm; 9 | 请你写一段代码来帮小明老师检查一下队伍吧。 10 | 11 | 关于输入 12 | 13 | 第一行一个整数n,表示后面有n种排队方式。接下来有2n行,每个奇数行为一个整数m, 14 | 接下来的一行为m个整数,代表每位同学的身高。1<=n<=10,1<=m<=100。身高的范围 15 | 表示为(0, 100]. 16 | 17 | 关于输出 18 | 19 | 输出共n行。对每种排队方式,如果是整齐的,输出Yes,否则输出No。 20 | 21 | 例子输入 22 | 23 | 5 24 | 1 25 | 50 26 | 3 27 | 6 6 6 28 | 5 29 | 10 30 50 70 90 30 | 6 31 | 65 55 45 50 55 60 32 | 10 33 | 51 52 53 54 55 54 53 52 51 50 34 | 35 | 例子输出 36 | 37 | Yes 38 | Yes 39 | Yes 40 | No 41 | Yes 42 | *****/ 43 | 44 | #include 45 | using namespace std; 46 | 47 | #define MAX_N 110 48 | 49 | int q[MAX_N] = {0}; 50 | int n = 0; 51 | 52 | bool check() 53 | { 54 | int l = 0, r = n - 1; 55 | while (l < r && q[l] <= q[l + 1]) // 从左向右递增 56 | l++; 57 | while (l < r && q[r - 1] >= q[r]) // 从右向左递减 58 | r--; 59 | return l == r; // 若l和r相遇,说明符合队形;否则不符合 60 | } 61 | 62 | int main() 63 | { 64 | int n_case = 0; 65 | cin >> n_case; 66 | while (n_case--) 67 | { 68 | cin >> n; 69 | for (int i = 0; i < n; i++) 70 | cin >> q[i]; 71 | if (check()) 72 | cout << "Yes" << endl; 73 | else 74 | cout << "No" << endl; 75 | } 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /第三阶段编程练习5/求数组不相邻元素之和的最大值.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 给定一个长度为n的数组,从其中任意选择不相邻的m个元素形成子数组,求这个子数组所有元素之和的最大值。 5 | 6 | 关于输入 7 | 8 | 输入包括两行。 9 | 第一行为一个正整数n(0<=n<=10000)。 10 | 第二行为n个整数,表示整个数组。 11 | 12 | 关于输出 13 | 14 | 输出一个数字,代表数组所有不相邻元素之和的最大值。 15 | 16 | 例子输入 17 | 18 | 5 19 | 20 | 1 2 3 4 5 21 | 22 | 例子输出 23 | 24 | 9 25 | *****/ 26 | 27 | #include 28 | #include 29 | using namespace std; 30 | 31 | /** 32 | 思路:动态规划 33 | 34 | 用nums表示数组,用dp[i]表示nums从0到i的前缀能形成的符合要求的子数组的和的最大值。 35 | 考虑dp[i](i > 1)要如何计算,有如下两种情况: 36 | 1. dp[i]对应的方案中没有取nums[i-1],那么此时nums[i]是可以取的,这种情况的子数组的和的最大值是dp[i-2] + nums[i]; 37 | 2. dp[i]对应的方案中取了nums[i-1],则此时nums[i]不能取,这种情况的子数组的和的最大值就是dp[i-1]。 38 | 两种情况中较大的方案就是dp[i]的方案,因此dp[i] = max(dp[i-2] + nums[i], dp[i-1])。 39 | 最后再考虑一下边界条件,dp[0]显然应该是nums[0],而dp[1] = max(nums[0], nums[1])。 40 | 从dp[2]开始逐个计算,最终dp[length(nums) - 1]就是所求的答案。 41 | 42 | 我们可以进一步优化这个过程。 43 | 简单观察可以发现在每一步dp[i]的计算过程中,始终都只与dp[i], dp[i-1], dp[i-2]和nums[i]四个数相关。 44 | 那么我们只需要在每一步保留这四个值即可,而不用保存全部nums和dp数组。 45 | **/ 46 | 47 | int main() 48 | { 49 | int n = 0, num = 0; 50 | int dp[3] = {0}; 51 | cin >> n; 52 | for (int i = 0; i < n; i++) 53 | { 54 | cin >> num; 55 | if (!i) 56 | dp[0] = num; 57 | else if (i == 1) 58 | dp[1] = max(dp[0], num); 59 | else 60 | dp[i % 3] = max(dp[(i - 2) % 3] + num, dp[(i - 1) % 3]); 61 | } 62 | cout << dp[(n - 1) % 3] << endl; 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /第三阶段编程练习3/回文字符串.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 回文就是正读和反读都一样的字符串,例如"radar", "a man, a plan, a canal, panama"(忽略空格和标点符号). 5 | 请编写程序,读入一行字符串,若为回文,则输出"true",否则输出"false". 6 | 7 | 关于输入 8 | 9 | 输入有若干行,每行一个字符串,长度不超过100 10 | 11 | 关于输出 12 | 13 | 对应于每一行输入,输出"true"或"false" 14 | 注意:忽略字符串中的空格和标点符号 15 | 16 | 例子输入 17 | 18 | radar 19 | , rada .'" r 20 | radAr 21 | 22 | 例子输出 23 | 24 | true 25 | true 26 | false 27 | *****/ 28 | 29 | #include 30 | #include 31 | #include 32 | using namespace std; 33 | 34 | #define MAX_LEN 110 35 | 36 | /** 移除所有src中所有空格和标点,结果存放在tgt中 **/ 37 | void remove_space_and_punctuation(char *src, char *tgt) 38 | { 39 | for (int i = 0, j = 0; src[i] != '\0'; i++) 40 | if ((src[i] >= 'a' && src[i] <= 'z') || 41 | (src[i] >= 'A' && src[i] <= 'Z') || 42 | (src[i] >= '0' && src[i] <= '9')) 43 | tgt[j++] = src[i]; 44 | } 45 | 46 | int main() 47 | { 48 | char buffer[MAX_LEN] = "", str[MAX_LEN] = ""; 49 | while(cin.getline(buffer, MAX_LEN, '\n')) 50 | { 51 | /** 移除空格和标点 **/ 52 | memset(str, '\0', sizeof(str)); 53 | remove_space_and_punctuation(buffer, str); 54 | 55 | /** 判断回文串 **/ 56 | strcpy(buffer, str); 57 | reverse(buffer, buffer + strlen(buffer)); 58 | if (!strcmp(buffer, str)) 59 | cout << "true" << endl; 60 | else 61 | cout << "false" << endl; 62 | } 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /第三阶段编程练习5/最长公共子序列.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 我们称一个字符的数组S为一个序列。对于另外一个字符数组Z,如果满足以下条件, 5 | 则称Z是S的一个子序列:(1)Z中的每个元素都是S中的元素(2)Z中元素的顺序与 6 | 在S中的顺序一致。例如:当S = (E,R,C,D,F,A,K)时,(E,C,F)和(E,R)等 7 | 等都是它的子序列。而(R,E)则不是。 8 | 现在我们给定两个序列,求它们最长的公共子序列的长度。 9 | 10 | 关于输入 11 | 12 | 一共两行,分别输入两个序列 13 | 14 | 关于输出 15 | 16 | 一行,输出最长公共子序列的长度。 17 | 18 | 例子输入 19 | 20 | ABCBDAB 21 | BDCABA 22 | 23 | 例子输出 24 | 25 | 4 26 | *****/ 27 | 28 | #include 29 | #include 30 | #include 31 | using namespace std; 32 | 33 | #define MAX_LEN 1000 34 | 35 | /** 36 | 思路:动态规划 37 | 38 | 两个字符串用a和b表示。 39 | 用dp[i][j]来记录a的长度为i的前缀和b的长度为j的前缀的最长公共子序列的长度。 40 | 显然,dp[i][0] = dp[0][j] = 0(对任意可行的i和j来说)。 41 | 假设对任意0 <= i < M和任意0 <= j < N的dp[i][j]都是已知的,求dp[M][N]就只有如下的两种情况: 42 | 1. a[M]和b[N]相同,则说明在M-1和N-1的基础之上公共子序列长度可以增长1,那么dp[M][N] = dp[M - 1][N - 1] + 1; 43 | 2. 否则,只能a的前缀或b的前缀回退一个字符,选取其中较大的方案,那么dp[M][N] = max(dp[M - 1][N], dp[M][N - 1])。 44 | 按上述计算方式,从dp[0][0]向右下计算即可,dp[strlen(a)][strlen(b)]便是需要求的答案。 45 | **/ 46 | 47 | char a[MAX_LEN] = "\0", b[MAX_LEN] = "\0"; 48 | int dp[MAX_LEN][MAX_LEN] = {0}; 49 | 50 | int main() 51 | { 52 | cin >> a >> b; 53 | for (int i = 0; a[i] != '\0'; i++) 54 | for (int j = 0; b[j] != '\0'; j++) 55 | { 56 | if (a[i] == b[j]) 57 | dp[i + 1][j + 1] = dp[i][j] + 1; 58 | dp[i + 1][j + 1] = max(dp[i + 1][j + 1], max(dp[i + 1][j], dp[i][j + 1])); 59 | } 60 | cout << dp[strlen(a)][strlen(b)] << endl; 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /综合练习/最短歧义串.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 对于一个字符串,如果我们可以用两种不同的办法把它切分成单词的序列,那么我们说这个字 5 | 符串是有歧义的.比如iskill,可以切分成is和kill,也可以切分成i和skill. 6 | 现在给你一个单词表,请你构造出在这个单词表上的最短歧义串,即这个串可以用两种方案切 7 | 分成单词表中的单词,要求歧义串尽可能短. 8 | 9 | 关于输入 10 | 11 | 第一行是一个整数n(n<=100)表示词表的大小. 12 | 接下来n行,每行一个单词,只包含数字和小写字母,长度不超过20. 13 | 14 | 关于输出 15 | 16 | 输出最短歧义串,如果最短歧义串有多种可能,请输出字典序最小的那一个. 17 | 18 | 例子输入 19 | 20 | 4 21 | i 22 | is 23 | kill 24 | skill 25 | 26 | 例子输出 27 | 28 | iskill 29 | *****/ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | using namespace std; 36 | 37 | #define MAX_N 110 38 | 39 | string dict[MAX_N] = {""}; // Word dictionary 40 | unordered_set h; // Hash 41 | queue q; // BFS queue 42 | int n = 0; 43 | 44 | int main() 45 | { 46 | cin >> n; 47 | for (int i = 0; i < n; i++) 48 | cin >> dict[i]; 49 | 50 | /** BFS **/ 51 | q.push(""); 52 | while (!q.empty()) 53 | { 54 | for (int i = 0; i < n; i++) 55 | if (h.find(q.front() + dict[i]) != h.end()) // Already in h 56 | { 57 | cout << q.front() + dict[i] << endl; // Output & return 58 | return 0; 59 | } 60 | else // Otherwise 61 | { 62 | h.insert(q.front() + dict[i]); // Insert into h & push into q 63 | q.push(q.front() + dict[i]); 64 | } 65 | q.pop(); 66 | } 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /第三阶段编程练习5/钢条切割问题.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | Serling公司购买长钢条,将其切割为短钢条出售。切割工序本身没有成本支出。公司管理层希望知道最 5 | 佳的切割方案。假定我们知道Serling公司出售一段长为i英寸的钢条的价格为pi(i=1,2,…,单位为美元)。 6 | 钢条的长度均为整英寸。 7 | 给定一段长度为n英寸的钢条和一个价格表pi(i=1,2,…n),求切割钢条方案,使得销售收益rn最大。 8 | 9 | 关于输入 10 | 11 | 第一行:n,表示购买的长钢条的长度。 12 | 接下来一行包含 n 个数字,第 i 个数字出售长为 i 的钢条的价格,即 pi。 13 | 其中 0 < n <= 3000,0 < pi <= 10000。 14 | 15 | 关于输出 16 | 17 | 输出仅一行,为最大的销售收益值 rn。 18 | 19 | 例子输入 20 | 21 | 7 22 | 1 5 8 9 10 17 17 23 | 24 | 例子输出 25 | 26 | 18 27 | 28 | 提示信息 29 | 30 | 注意,如果长度为n英寸的钢条的价格pn足够大,最优解可能就是完全不需要切割。 31 | *****/ 32 | 33 | #include 34 | #include 35 | using namespace std; 36 | 37 | #define MAX_N 5000 38 | 39 | /** 40 | 思路:动态规划 41 | 42 | 用dp[x]表示长度为x的钢条在最优切割方案下可以卖出的价格。显然,dp[0] = 0。 43 | 假设长度为dp[1]到dp[L - 1]都是已知的,求dp[L]就只需要考虑如下的两种情况: 44 | 1. 不切割,直接出售长度为L的钢条; 45 | 2. 将L切成L1和L2两段(0 < L1 <= l2 < L),每一段都按已知的最优dp[L1]和dp[L2]进行切割。 46 | 那么显然就有: 47 | dp[L] = max(p[L], dp[1] + dp[L - 1], dp[2] + dp[L - 2], ...) 48 | 49 | 基于上面的推理,我们不难发现可以从dp[1]开始,从小到大计算dp[x],最终dp[n]就是所需要的答案。 50 | **/ 51 | 52 | int dp[MAX_N] = {0}; 53 | int p[MAX_N] = {0}; 54 | 55 | int main() 56 | { 57 | int n = 0; 58 | cin >> n; 59 | for (int i = 1; i <= n; i++) 60 | cin >> p[i]; 61 | dp[0] = 0; 62 | for (int i = 1; i <= n; i++) 63 | { 64 | dp[i] = p[i]; // 不切割 65 | for (int j = 1; j + j <= i; j++) // 只用考虑i的一半,避免重复计算 66 | dp[i] = max(dp[i], dp[j] + dp[i - j]); // 将i切割为j和i - j两段 67 | } 68 | cout << dp[n] << endl; 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /期末考试/世界杯只因.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 卡塔尔世界杯正在火热进行中,P大富哥李哥听闻有一种叫"肤白·态美·宇宙无敌·世界杯·预测鸡"的鸡品种(以下 5 | 简称为只因)有概率能准确预测世界杯赛果,一口气买来无数只只因,并把它们塞进了N个只因窝里,但只因窝实在太 6 | 多了,李哥需要安装摄像头来观测里面的只因的预测行为。 7 | 具体来说,李哥的只因窝可以看作分布在一条直线上的N个点,编号为1到N。由于每个只因窝的结构不同,在编号为i 8 | 的只因窝处安装摄像头,观测范围为a_i,其中a是长为N的整数列,表示若在此安装摄像头,可以观测到编号在 9 | [ i - a_i , i + a_i ](闭区间)内的所有只因窝。 10 | 李哥觉得摄像头成本高,决定抠门一下,请你来帮忙看看最少需要安装多少个摄像头,才能观测到全部N个只因窝。作 11 | 为回报,他会请你喝一杯芋泥波波牛乳茶。 12 | 13 | 关于输入 14 | 15 | 第一行:一个正整数,代表有N个只因窝。 16 | 第二行给出数列a:N个非负整数,第i个数代表a_i,也就是在第i个只因窝装摄像头能观测到的区间的半径。 17 | 数据保证 N ≦ 500000,0 ≦ a_i ≦ N 18 | 19 | 关于输出 20 | 21 | 一个整数,即最少需要装的摄像头数量。 22 | 23 | 例子输入 24 | 25 | 10 26 | 2 0 1 1 0 3 1 0 2 0 27 | 28 | 例子输出 29 | 30 | 3 31 | 32 | 提示信息 33 | 34 | 由于数据量较大,建议使用scanf进行读入,即 35 | int n; 36 | scanf("%d", &n); 37 | 请注意所使用算法的运行效率 38 | 彩蛋:只因们很喜欢那个穿着蓝白球衣长得像黄金矿工的10号 39 | *****/ 40 | 41 | #include 42 | #include 43 | #include 44 | using namespace std; 45 | 46 | #define MAXN 500500 47 | 48 | int dp[MAXN] = {0}; 49 | 50 | int main() 51 | { 52 | int n = 0, s = 0, l = 0, r = 0; 53 | scanf("%d", &n); 54 | memset(dp, 0x7f, sizeof(dp)); 55 | dp[0] = 0; 56 | for (int i = 1; i <= n; i++) 57 | { 58 | scanf("%d", &s); 59 | l = max(1, i - s); 60 | r = min(n, i + s); 61 | if (dp[r] > dp[l - 1] + 1) 62 | for (int j = l; j <= r; j++) 63 | dp[j] = min(dp[j], dp[l - 1] + 1); 64 | if (dp[n] < 0x7f7f7f7f) 65 | break; 66 | } 67 | printf("%d\n", dp[n]); 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /综合练习/迷信的病人.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 医院为了方便对患者进行建档和管理,引入了9位整数ID号来标识每个病人。最近医院入住了 5 | 一个迷信的病人,他认为ID号的好坏直接决定了自己的命运。他对ID号x有如下要求: 6 | (1)x的前三位数构成的整数是素数 7 | (2)x的后三位数构成的整数是平方数(所谓平方数,是指它是某一个正整数的平方,e.g. 8 | 1,4,9,16...) 9 | (3)x中不包含"13" 10 | 为了避免不必要的医患矛盾,医院须尽量满足他的需求。现给定正整数区间[m,n],请你判断 11 | 存在几个满足病人需求的ID号。 12 | 13 | 关于输入 14 | 15 | 两个正整数m,n,以空格隔开。(999999999>=n>=m>=111111111) 16 | 17 | 关于输出 18 | 19 | 一个整数(满足要求的ID的个数)。 20 | 21 | 例子输入 22 | 23 | 157689476 157689687 24 | 25 | 例子输出 26 | 27 | 5 28 | 29 | 提示信息 30 | 31 | 存在5个满足要求的ID:157689484,157689529,157689576,157689625,157689676 32 | *****/ 33 | 34 | #include 35 | #include 36 | 37 | #define MAX_LEN 10 38 | 39 | bool contain_13(int n) 40 | { 41 | char buf[MAX_LEN] = ""; 42 | sprintf(buf, "%d", n); 43 | if (strstr(buf, "13")) 44 | return true; 45 | return false; 46 | } 47 | 48 | bool is_prime(int n) 49 | { 50 | if (!n || n == 1) 51 | return false; 52 | for (int i = 2; i * i <= n; i++) 53 | if (!(n % i)) 54 | return false; 55 | return true; 56 | } 57 | 58 | bool is_square(int n) 59 | { 60 | for (int i = 1; i * i <= n; i++) 61 | if (i * i == n) 62 | return true; 63 | return false; 64 | } 65 | 66 | int main() 67 | { 68 | int m = 0, n = 0; 69 | int ans = 0; 70 | scanf("%d%d", &m, &n); 71 | for (int i = m; i <= n; i++) 72 | if (!contain_13(i) && is_prime(i / 1000000) && is_square(i % 1000)) 73 | ans++; 74 | printf("%d\n", ans); 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /综合练习/笨小嗨.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 笨小嗨的词汇量很小,所以每次做英语选择题的时候都很头疼。但是他找到了一种方法,经试验证明, 5 | 用这种方法去选择选项的时候选对的几率非常大! 6 | 这种方法的具体描述如下:假设maxn是单词中出现次数最多的字母的出现次数,minn是单词中出现次数 7 | 最少的字母的出现次数,如果maxn-minn是一个质数,那么笨小嗨就认为这是个Lucky Word,这样的单 8 | 词很可能就是正确的答案。 9 | 10 | 关于输入 11 | 12 | 输入只有一行,是一个单词,其中只可能出现小写字母,并且长度小于100。 13 | 14 | 关于输出 15 | 16 | 输出共两行,第一行是一个字符串,假设输入的的单词是Lucky Word,那么输出“Lucky Word”,否 17 | 则输出“No Answer”;(注意:不包含引号) 18 | 第二行是一个整数,如果输入单词是Lucky Word,输出maxn-minn的值,否则输出0。 19 | 20 | 例子输入 21 | 22 | error 23 | 24 | 例子输出 25 | 26 | Lucky Word 27 | 2 28 | 29 | 提示信息 30 | 31 | 单词error中出现最多的字母r出现了3次,出现次数最少的字母出现了1次,3-1=2,2是质数。 32 | *****/ 33 | 34 | #include 35 | #include 36 | using namespace std; 37 | 38 | #define MAX_C 300 39 | #define MAX_L 110 40 | #define MAX_INT 0x7fffffff 41 | 42 | int cnt[MAX_C] = {0}; 43 | char s[MAX_L] = ""; 44 | 45 | bool is_prime(int n) 46 | { 47 | if (!n || n == 1) 48 | return false; 49 | for (int i = 2; i * i <= n; i++) 50 | if (!(n % i)) 51 | return false; 52 | return true; 53 | } 54 | 55 | int main() 56 | { 57 | int maxn = 0, minn = MAX_INT; 58 | cin >> s; 59 | for (int i = 0; s[i] != '\0'; i++) 60 | cnt[s[i]]++; 61 | for (int i = 0; i < MAX_C; i++) 62 | if (cnt[i]) 63 | { 64 | maxn = max(maxn, cnt[i]); 65 | minn = min(minn, cnt[i]); 66 | } 67 | if (is_prime(maxn - minn)) 68 | cout << "Lucky Word" << endl << maxn - minn << endl; 69 | else 70 | cout << "No Answer" << endl << 0 << endl; 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /第四阶段编程练习1/石子归并.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 现摆一排 N 堆石子(N ≤ 100),要将石子有次序地合并成一堆。规定每次只能选 5 | 取相邻的两堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。编一 6 | 程序,由文件读入堆数 N 及每堆的石子数( ≤ 20)。选择一种合并石子的方案, 7 | 使所做 N-1 次合并,得分的总和最小。 8 | 9 | 关于输入 10 | 11 | 第一行为石子堆数 N;第二行为每堆石子数,数字之间用一个空格分隔。 12 | 13 | 关于输出 14 | 15 | 最小的得分总和。 16 | 17 | 例子输入 18 | 19 | 21 20 | 17 2 9 20 9 5 2 15 14 20 19 19 1 9 8 8 9 14 9 4 8 21 | 22 | 例子输出 23 | 24 | 936 25 | 26 | 提示信息 27 | 28 | 求解不当,可能超时。 29 | *****/ 30 | 31 | #include 32 | #include 33 | using namespace std; 34 | 35 | #define MAX_N 110 36 | #define MAX_INT 0x7fffffff 37 | 38 | /** 39 | 思路 -- 动态规划 + 前缀和 40 | 41 | 前缀和在之前已经介绍过,参考第三阶段编程练习5的最优路径一题示例。 42 | 用psum[i]表示pile[0]到pile[i]的和(pile下标从1开始,pile[0] = 0)。 43 | 那么pile中任意i到j的和sum(i,j)就可以用psum数组求取: 44 | sum(i,j) = psum[j] - psum[i-1]。 45 | 46 | 用dp[i][j]表示从pile[i]到pile[j]的最小合并方案的分数。 47 | 我们可以从i、j中找到k,使得从k合i到j区间的方案是最小的。 48 | 不断递推求取dp数组,dp[1][n]即为所求答案。 49 | **/ 50 | 51 | int pile[MAX_N] = {0}, psum[MAX_N] = {0}; 52 | int dp[MAX_N][MAX_N] = {0}; 53 | 54 | int main() 55 | { 56 | int n = 0, tmp = 0; 57 | cin >> n; 58 | for (int i = 1; i <= n; i++) 59 | { 60 | cin >> pile[i]; 61 | psum[i] = psum[i - 1] + pile[i]; 62 | } 63 | for (int i = 1; i < n; i++) 64 | for (int j = 1; j + i <= n; j++) 65 | { 66 | tmp = i + j; 67 | dp[j][tmp] = MAX_INT; 68 | for (int k = j; k <= tmp; k++) 69 | dp[j][tmp] = min(dp[j][tmp], dp[j][k] + dp[k + 1][tmp] + psum[tmp] - psum[j - 1]); 70 | } 71 | cout << dp[1][n]; 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /综合练习/简单括号匹配.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 在程序设计中,括号常用于表示运算的优先顺序。括号总是成对出现的。当每个正括号的右边有相匹配的反括号, 5 | 并且每个反括号的左边有相匹配的正括号时,就认为括号匹配。像式子:(3+4)*(5 以及(3+4))*(5 ,括号就不匹 6 | 配。输入带有圆括号的式子后,请检验其中的圆括号是否匹配(假设输入的符号数不超过300个)。若不匹配,则输 7 | 出mismatch;若匹配,则输出匹配对(在序列中的位置) 8 | 注意:字符串从 0 开始编号,即:起始字符的编号为 0 9 | 10 | 关于输入 11 | 12 | 带圆括号的一串符号 13 | 14 | 关于输出 15 | 16 | 若圆括号不匹配,则输出 mismatch 17 | 否则,输出匹配对,每行输出1对(左括号的位置以及相应的右扩号位置),以逗号间隔;下一行的左括号位置值 18 | 大于上一行的左括号位置值 19 | 20 | 例子输入 21 | 22 | (abc+5)def(()edf) 23 | 24 | 例子输出 25 | 26 | 0,6 27 | 10,16 28 | 11,12 29 | *****/ 30 | 31 | #include 32 | #include 33 | using namespace std; 34 | 35 | #define MAX_LEN 1010 36 | 37 | char s[MAX_LEN] = "\0"; 38 | int st[MAX_LEN] = {0}, n_st = 0; 39 | 40 | struct Pair 41 | { 42 | int l; 43 | int r; 44 | } ans[MAX_LEN] = {{0, 0}}; 45 | int n_ans = 0; 46 | 47 | bool cmp(const Pair &a, const Pair &b) 48 | { 49 | return a.l < b.l; 50 | } 51 | 52 | bool match() 53 | { 54 | for (int i = 0; s[i] != '\0'; i++) 55 | if (s[i] == '(') 56 | st[n_st++] = i; 57 | else if (s[i] == ')') 58 | { 59 | if (!n_st) 60 | return false; 61 | ans[n_ans].l = st[--n_st]; 62 | ans[n_ans++].r = i; 63 | } 64 | return !n_st; 65 | } 66 | 67 | int main() 68 | { 69 | cin >> s; 70 | if (match()) 71 | { 72 | sort(ans, ans + n_ans, cmp); 73 | for (int i = 0; i < n_ans; i++) 74 | cout << ans[i].l << "," << ans[i].r << endl; 75 | } 76 | else 77 | cout << "mismatch" << endl; 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /2021年期末考试题/天平.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | Gigel有一个奇怪的天平,他想要使它平衡。事实上,这个东西与其他普通的天平是不同的。 5 | 它有两条重量可以忽略的臂,每条臂的长度是15。臂上有一些挂钩,Gigel想要从他拥有的G 6 | 个重物中(1 <= G <= 20)挂一些上去,这些重物有着不同的重量,重量范围在1到25之间。 7 | Gigel可以把任意的重物放到任意的挂钩上,但他必须全部用完所有重物。 8 | 最终,Gigel成功地利用他在全国信息学奥赛中的经验将天平弄平衡了。现在他想知道有多 9 | 少种方式可以让它平衡。 10 | 挂钩的位置和重物的重量是已知的,写一个程序来计算能使天平平衡的所有可能数目。 11 | 测试样例保证至少有一种能使之平衡的方案。 12 | 13 | 关于输入 14 | 15 | 输入由以下组成: 16 | • 第一行包含整数C(2 <= C <= 20)和整数G(2 <= G <= 20); 17 | • 下一行包含C个整数(这些数字也是互不相同的,按递增排序),范围在-15到15之间,代 18 | 表挂钩的分配;每个数字代表在X轴上相对天平中心的位置(当没有重物在天平上时,天平沿 19 | X轴方向平衡。距离的绝对值代表挂钩与天平中心的距离,数字的符号决定挂钩在哪个臂上: 20 | 负号代表在左臂,正号代表在右臂) 21 | • 再下一行是G个互不相同的自然数,按递增排序,范围在1到25之间,代表重物的重量值。 22 | 23 | 关于输出 24 | 25 | 输出包含一个数M,代表使天平平衡的可能方案个数。 26 | 27 | 例子输入 28 | 29 | 2 4 30 | -2 3 31 | 3 4 5 8 32 | 33 | 例子输出 34 | 35 | 2 36 | 37 | 提示信息 38 | 39 | 为了与POJ中保持一致,输出结果在可以用int表示的范围内。 40 | 使用动态规划。 41 | *****/ 42 | 43 | 44 | #include 45 | using namespace std; 46 | 47 | #define MAX_N 30 48 | #define BALANCE (15 * 20 * 20) 49 | #define MAX_W (BALANCE * 2 + 10) 50 | 51 | int dp[MAX_N][MAX_W] = {0}; 52 | int L[MAX_N] = {0}, w[MAX_N] = {0}; 53 | 54 | int main() 55 | { 56 | int C = 0, G = 0; 57 | cin >> C >> G; 58 | for(int i = 1;i<=C;i++) 59 | cin>>L[i]; 60 | for(int i=1;i<=G;i++) 61 | cin>>w[i]; 62 | 63 | dp[0][BALANCE] = 1; 64 | for(int i = 1; i <= G; i++) 65 | for(int j = 1; j <= MAX_W; j++) 66 | if(dp[i - 1][j]) 67 | for(int k = 1; k <= C; k++) 68 | dp[i][j + w[i] * L[k]] += dp[i - 1][j]; 69 | cout< 44 | using namespace std; 45 | 46 | #define MAX_F 400010 47 | #define MAX_TRIAL 30 48 | 49 | int F = 0, E = 0; 50 | int dp[MAX_F][MAX_TRIAL] = {0}; 51 | 52 | int main() 53 | { 54 | for (int i = 0; i < MAX_TRIAL; ++i) 55 | dp[1][i] = i; 56 | for (int i = 2; i < MAX_F; ++i) 57 | for (int cnt = 1; cnt <= 25; ++cnt) 58 | dp[i][cnt] = 1 + dp[i - 1][cnt - 1] + dp[i][cnt - 1]; 59 | while (cin >> F >> E) 60 | { 61 | if (!F && !E) 62 | break; 63 | if (E == 1) 64 | { 65 | cout << F << endl; 66 | continue; 67 | } 68 | for (int i = 0; i < MAX_TRIAL; i++) 69 | if (dp[E][i] >= F) 70 | { 71 | cout << i << endl; 72 | break; 73 | } 74 | } 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /第四阶段编程练习2/简单括号匹配.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 在程序设计中,括号常用于表示运算的优先顺序。括号总是成对出现的。当每个正括号的右边有相匹配的反括号, 5 | 并且每个反括号的左边有相匹配的正括号时,就认为括号匹配。像式子:(3+4)*(5 以及(3+4))*(5 ,括号就不匹 6 | 配。输入带有圆括号的式子后,请检验其中的圆括号是否匹配(假设输入的符号数不超过300个)。若不匹配,则输 7 | 出mismatch;若匹配,则输出匹配对(在序列中的位置) 8 | 注意:字符串从 0 开始编号,即:起始字符的编号为 0 9 | 10 | 关于输入 11 | 12 | 带圆括号的一串符号 13 | 14 | 关于输出 15 | 16 | 若圆括号不匹配,则输出 mismatch 17 | 否则,输出匹配对,每行输出1对(左括号的位置以及相应的右扩号位置),以逗号间隔;下一行的左括号位置值 18 | 大于上一行的左括号位置值 19 | 20 | 例子输入 21 | 22 | (abc+5)def(()edf) 23 | 24 | 例子输出 25 | 26 | 0,6 27 | 10,16 28 | 11,12 29 | *****/ 30 | 31 | #include 32 | #include 33 | using namespace std; 34 | 35 | #define MAX_LEN 1010 36 | 37 | char s[MAX_LEN] = "\0"; 38 | int st[MAX_LEN] = {0}, n_st = 0; // 栈 39 | 40 | struct Pair 41 | { 42 | int l; 43 | int r; 44 | } ans[MAX_LEN] = {{0, 0}}; // 存放匹配结果 45 | int n_ans = 0; 46 | 47 | bool cmp(const Pair &a, const Pair &b) 48 | { 49 | return a.l < b.l; 50 | } 51 | 52 | bool match() 53 | { 54 | for (int i = 0; s[i] != '\0'; i++) 55 | if (s[i] == '(') // 入栈 56 | st[n_st++] = i; 57 | else if (s[i] == ')') // 出栈 58 | { 59 | if (!n_st) 60 | return false; 61 | ans[n_ans].l = st[--n_st]; 62 | ans[n_ans++].r = i; 63 | } 64 | return !n_st; 65 | } 66 | 67 | int main() 68 | { 69 | cin >> s; 70 | if (match()) 71 | { 72 | sort(ans, ans + n_ans, cmp); 73 | for (int i = 0; i < n_ans; i++) 74 | cout << ans[i].l << "," << ans[i].r << endl; 75 | } 76 | else 77 | cout << "mismatch" << endl; 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /第三阶段编程练习3/和为定值的子集数.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 已知 n 个正整数,wi (1≤i≤n) 形成一个集合 W={w1,w2,...,wn},集合中的元素彼此不相同。 5 | 给定某个正整数 M ,集合W中可否存在子集,该子集的所有元素之和和恰好为M,问:这样的子集有 6 | 多少个? 7 | 例如,4个正整数为: 8 | 11 13 24 7 9 | 若给定M=31,则有两个子集{7,11,13}和{7,24} 10 | 于是,这样的子集有 2 个。 11 | 12 | 关于输入 13 | 14 | 第1行,输入若干个正整数,表示集合的元素,各整数之间以空格间隔; 15 | 后面有多行,每行表示一个 M 值;若某行的 M 值为0,则结束。 16 | 17 | 关于输出 18 | 19 | 对应的每个有效的 M 值,输出相应行的子集数目 20 | 21 | 例子输入 22 | 23 | 11 13 24 7 24 | 31 25 | 24 26 | 45 27 | 55 28 | 0 29 | 30 | 例子输出 31 | 32 | 2 33 | 2 34 | 0 35 | 1 36 | *****/ 37 | 38 | #include 39 | #include 40 | using namespace std; 41 | 42 | #define MAX_N 5000 43 | 44 | int w[MAX_N] = {0}, n = 0; // 集合 45 | int ans = 0; // 搜索结果 46 | 47 | /** 深度优先搜索 **/ 48 | void dfs(int step, int val) // step为当前需要考虑的数字,val为要达成的求和目标 49 | { 50 | if (val <= 0) // 若值小于等于0 51 | { // 搜索结束 52 | if (!val) // 若值为0 53 | ans++; // 说明搜索到一个子集,ans加1 54 | return; 55 | } 56 | if (step >= n) // 若step大于等于n 57 | return; // 同样搜索结束 58 | dfs(step + 1, val); // 不算step,递归搜索 59 | dfs(step + 1, val - w[step]); // 算上step,递归搜索 60 | } 61 | 62 | int main() 63 | { 64 | char c = '\0'; 65 | int m = 0; 66 | 67 | /** 读入数据并排序 **/ 68 | while (cin >> w[n++]) 69 | { 70 | cin.get(c); 71 | if (c == '\n') 72 | break; 73 | } 74 | sort(w, w + n); // 排序可以一定程度上加快搜索过程 75 | 76 | while (cin >> m) 77 | { 78 | if (!m) 79 | return 0; 80 | ans = 0; 81 | dfs(0, m); 82 | cout << ans << endl; 83 | } 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /第四阶段编程练习1/自己动手丰衣足食.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 经历过和S星人的交流之后,他已经对任何交流上的差异都不感到奇怪了。然而这一次,他在和一个A国同学合作 5 | 时又出现了让他大跌眼镜的事情。那个同学给他的实验数据是用科学计数法表示的,而他需要正常的保留小数点 6 | 后6位的双精度浮点数。可是不同于我们用2e5来表示200000,他们会使用任何一个字母或者数字中不会出现的字 7 | 符来表示乘方。这下可麻烦了,本来好好的用atof()函数就解决了,现在这个写好的函数就没法用,只好自己写 8 | 一个了。阿福为了这份数据已经熬了好几个通宵了,想让你趁他睡觉把这个问题处理一下,你一定可以做到的! 9 | (助教哥哥友情提醒,题目较长,记得看提示) 10 | 11 | 关于输入 12 | 13 | 输入多个数字型的字符串,每个字符串之间换行符隔开。字符串可能包括正负符号、小数点以及代表乘方的字符 14 | (不是数字,正负号,小数点)。 15 | 对输入的字符串进行转换时,遇见数字、小数点或正负符号就开始做转换,字符串结束时才结束转换,并将结果 16 | 返回。 17 | 当输入字符'q'时,程序结束。 18 | 19 | 关于输出 20 | 21 | double型浮点数,显示小数点后六位。 22 | 当为正数时,浮点数第一位不显示'+'。 23 | 当为负数时,浮点数第一位显示'-'. 24 | 25 | 例子输入 26 | 27 | +2343.12 28 | -2.36542 29 | -5.21 30 | 6.348 31 | +0.564f5 32 | +0.456 33 | -25.1f-5 34 | q 35 | 36 | 例子输出 37 | 38 | 2343.120000 39 | -2.365420 40 | -5.210000 41 | 6.348000 42 | 56400.000000 43 | 0.456000 44 | -0.000251 45 | 46 | 提示信息 47 | 48 | 注意:本题严禁使用stdlib.h中的atof()函数,否则不得分。 49 | *****/ 50 | 51 | #include 52 | #include 53 | 54 | #define MAX_LEN 1000 55 | 56 | char buf[MAX_LEN] = "\0"; 57 | 58 | int main() 59 | { 60 | double num = 0; 61 | while (scanf("%[^\n]", buf) != EOF) 62 | { 63 | if (!strcmp("q", buf)) 64 | return 0; 65 | for (int i = 0; buf[i] != '\0'; i++) 66 | if (!(buf[i] >= '0' && buf[i] <= '9') && buf[i] != '+' && buf[i] != '-' && buf[i] != '.') 67 | { 68 | buf[i] = 'e'; // 将不规范的形式改为规范的科学技术法形式 69 | break; 70 | } 71 | sscanf(buf, "%lf", &num); // 将字符串转为double 72 | printf("%.6lf\n", num); 73 | scanf("%s", buf); // 读取缓冲区回车 74 | } 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /第四阶段编程练习2/鹰蛋.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 有一个教授有一批一模一样的鹰蛋。有一天他来到了一栋楼的脚下,他突然想知道自己的鹰蛋从这栋楼 5 | 的多少层扔下时恰好不碎。 6 | 一颗鹰蛋如果从i层摔下没有碎,那么从小于j层摔下也不会碎,如果从j层摔下碎了,从大于j层摔下也 7 | 会摔碎。如果恰好存在一层n,从n层摔下鹰蛋未碎,而从n+1层摔下碎了,那么这批鹰蛋恰好从n层摔下 8 | 未碎。如果从第一层摔下碎了,那么称恰好从0层摔下未碎;另一方面,如果从最高层(N层)摔下未碎, 9 | 那么称恰好从N层摔下未碎 10 | 这个教授想知道从第多少层恰好摔下不碎,但是这个教授想使用最少的试验次数来得到这个值。 11 | 现已知鹰蛋的个数M和楼层高度N,试问在最坏情况下,这个教授最少需要试验多少次来得到他想要的结 12 | 果? 13 | 比如:M为1,N为3。那么这个教授为了得到结果,就必须从一层一层测试,在最坏情况下,最少需要3 14 | 次试验。但是如果M=2,N=3,那么他就可以第一次从二层扔下,不管碎了还是没碎,他都只需再扔一次 15 | 即可得到结果,即需要做2次试验即可。 16 | 17 | 关于输入 18 | 19 | 有多组输入,每一组输入单独一行。 20 | 分别为两个如题所述的正整数N(大于0小于400001),M (大于0小于N+1)中间用空格隔开。 21 | 如果得到的N和M都为0,表示输入结束。 22 | 23 | 关于输出 24 | 25 | 每组输出单独一行,输出需要试验的次数K。 26 | 27 | 例子输入 28 | 29 | 100 1 30 | 100 2 31 | 0 0 32 | 33 | 例子输出 34 | 35 | 100 36 | 14 37 | 38 | 提示信息 39 | 40 | 动态规划,由于输入量比较大,最好尽量优化算法。。 41 | *****/ 42 | 43 | #include 44 | using namespace std; 45 | 46 | #define MAX_F 400010 47 | #define MAX_TRIAL 30 48 | 49 | int F = 0, E = 0; // Floor & Egg 50 | int dp[MAX_F][MAX_TRIAL] = {0}; // dp[i][j]表示i个鸡蛋尝试j次时,最多能对应几层楼 51 | 52 | int main() 53 | { 54 | for (int i = 0; i < MAX_TRIAL; ++i) 55 | dp[1][i] = i; 56 | for (int i = 2; i < MAX_F; ++i) 57 | for (int cnt = 1; cnt <= 25; ++cnt) 58 | dp[i][cnt] = 1 + dp[i - 1][cnt - 1] + dp[i][cnt - 1]; 59 | while (cin >> F >> E) 60 | { 61 | if (!F && !E) 62 | break; 63 | if (E == 1) 64 | { 65 | cout << F << endl; 66 | continue; 67 | } 68 | for (int i = 0; i < MAX_TRIAL; i++) 69 | if (dp[E][i] >= F) 70 | { 71 | cout << i << endl; 72 | break; 73 | } 74 | } 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /第三阶段编程练习4/查看菌落数目.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 菌落的数量对医生来说一直是一个很重要的数据,但是细菌数量太多人工又无法计数,因此你能写个程序帮助医生完成这个任务么? 5 | 有一张n*m的菌落的显微镜照片,每个格子是0(表示当前位置无细菌)或者1(表示当前位置是细菌),请你输出这张照片中菌落的数量。 6 | 如果一个细菌,其上下左右四个方向有细菌的话,则这些相邻的细菌属于一个菌落。 7 | 例如给定如下照片: 8 | 0 0 1 0 9 | 0 1 0 1 10 | 1 1 0 0 11 | 则给出的照片一共有A,B,C三个菌落,如下: 12 | 0 0 A 0 13 | 0 B 0 C 14 | B B 0 0 15 | 16 | 关于输入 17 | 18 | 输入数据第一行两个整数n,m(1<=n,m<=100),表示照片的长和宽。 19 | 接下来n行,每行都有m个用空格隔开的整数(0或者1),表示这一照片行的状态(有无细菌)。 20 | 21 | 关于输出 22 | 23 | 输出一个整数,表示该张照片中菌落数量 24 | 25 | 例子输入 26 | 27 | 3 5 28 | 0 0 1 0 1 29 | 0 1 0 1 1 30 | 1 1 0 0 1 31 | 32 | 例子输出 33 | 34 | 3 35 | *****/ 36 | 37 | #include 38 | #include 39 | using namespace std; 40 | 41 | #define MAX_N 200 42 | #define GERM '1' 43 | #define EMPTY '0' 44 | #define ND 4 45 | 46 | char arr[MAX_N][MAX_N] = {""}; 47 | int row = 0, col = 0; 48 | int dr[ND] = {0, 0, 1, -1}; 49 | int dc[ND] = {1, -1, 0, 0}; 50 | 51 | /** 深度优先搜索,移除当前菌落 **/ 52 | void dfs(int r, int c) 53 | { 54 | if (arr[r][c] == EMPTY) 55 | return; 56 | arr[r][c] = EMPTY; 57 | for (int d = 0; d < ND; d++) 58 | dfs(r + dr[d], c + dc[d]); 59 | } 60 | 61 | int main() 62 | { 63 | int cnt = 0; 64 | cin >> row >> col; 65 | memset(arr, EMPTY, sizeof(arr)); 66 | for (int i = 1; i <= row; i++) 67 | for (int j = 1; j <= col; j++) 68 | cin >> arr[i][j]; 69 | for (int i = 1; i <= row; i++) 70 | for (int j = 1; j <= col; j++) 71 | if (arr[i][j] == GERM) // 每当遇到细菌 72 | { 73 | cnt++; // 菌落计数加一 74 | dfs(i, j); // 移除该菌落 75 | } 76 | cout << cnt << endl; 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /第四阶段编程练习1/土豪的月收入.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 阿福因为程序写的好,阿拉伯酋长希望拉他去当王子,条件是让阿福写个程序统计国家每个月卖石油的收入。 5 | 阿福觉得这个机会也可以让他成为没有大学文凭却走上人生巅峰的众多传奇人物中的一员。乔布斯,比尔盖茨 6 | 不都没有大学毕业嘛!可是按照当地的货币单位,每个月的收入太大了用int以至于long long也存不下了, 7 | 为了成功娶到名叫钱多多的阿拉伯公主,阿福决定拼一把。 8 | 每个月的账单包括n条收入记录,每条记录是长度不大于200的一个正整数,设计一个程序,计算出每个月的 9 | 总收入。 10 | 11 | 关于输入 12 | 13 | 输入第一行为一个整数n,代表共有n个收入记录,输入保证n大于2但不大于100 14 | 接下来是n行,每行为一个长度不大于200的正整数 15 | 16 | 关于输出 17 | 18 | 输出为一行,代表所有收入的总和,结果中不能有多余的前导0。 19 | 20 | 例子输入 21 | 22 | 5 23 | 18446744073709551616 24 | 4294967296 25 | 0088888888888888888888888 26 | 1233211234567 27 | 12345567896666666661666616 28 | 29 | 例子输出 30 | 31 | 12434475232300866766308983 32 | *****/ 33 | 34 | #include 35 | #include 36 | #include 37 | using namespace std; 38 | 39 | #define MAX_LEN 300 40 | char *a = NULL, *b = NULL; 41 | 42 | void add() 43 | { 44 | int c = 0; 45 | reverse(a, a + strlen(a)); 46 | reverse(b, b + strlen(b)); 47 | if (strlen(a) < strlen(b)) 48 | for (int i = strlen(a); b[i] != '\0'; i++) 49 | a[i] = '0'; 50 | else 51 | for (int i = strlen(b); a[i] != '\0'; i++) 52 | b[i] = '0'; 53 | for (int i = 0; a[i] != '\0'; i++) 54 | { 55 | a[i] = a[i] - '0' + b[i] - '0' + c; 56 | c = a[i] / 10; 57 | a[i] = '0' + (a[i] % 10); 58 | } 59 | if (c) 60 | a[strlen(a)] = '0' + c; 61 | reverse(a, a + strlen(a)); 62 | } 63 | 64 | int main() 65 | { 66 | int n = 0; 67 | a = new char[MAX_LEN]; 68 | b = new char[MAX_LEN]; 69 | cin >> n; 70 | cin >> a; 71 | while(--n) 72 | { 73 | cin >> b; 74 | add(); 75 | } 76 | cout << a << endl; 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /2020年期末考试题/计算字符串的相似度.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 在计算机程序中,往往会大量使用字符串。对于不同的字符串,我们总希望能够有办法判断其相似度。 5 | 因此,我们定义了一套操作方法来把两个不同的字符串变得相同。 6 | 具体可选的操作方法有: 7 | 1. 修改一个字符,例如将"a"修改为"b"; 8 | 2. 增加一个字符,例如将"abdd"变为"aebdd" 9 | 3. 删除一个字符,例如将"travelling"变为"traveling" 10 | 例如,对于两个字符串"abcdefg"和"abcdef"两个字符串来说,我们可以通过“将前一个字符串减少一 11 | 个g”或者“给后一个字符串增加一个g”这两种方式来使得它们相同,这两种方案,都仅需要一次操作。 12 | 将修改字符串操作需要的最少的次数定义为两个字符串之间的距离,而相似度等于“距离+1”的倒数。 13 | 例如,上例中"abcdefg"和"abcdef"的距离为1,则其相似度为1/2=0.5. 14 | 给定任意两个字符串(长度20以内),写出一个程序来求出它们的相似度。 15 | 16 | 关于输入 17 | 18 | 第一行有一个整数n。表示测试数据的组数, 19 | 接下来共n行,每行两个字符串,用空格隔开。表示要计算距离的两个字符串 20 | 字符串长度不超过20。 21 | 22 | 关于输出 23 | 24 | 针对每一组测试数据输出两个字符串的相似度,保留小数点后6位。 25 | 26 | 例子输入 27 | 28 | 3 29 | abcdefg abcdef 30 | ab ab 31 | mnklj jlknm 32 | 33 | 例子输出 34 | 35 | 0.500000 36 | 1.000000 37 | 0.200000 38 | *****/ 39 | 40 | #include 41 | #include 42 | #include 43 | using namespace std; 44 | 45 | #define MAX_LEN 30 46 | int dp[MAX_LEN][MAX_LEN] = {0}; 47 | 48 | int main() 49 | { 50 | int n = 0, l1 = 0, l2 = 0; 51 | char s1[MAX_LEN] = "", s2[MAX_LEN] = ""; 52 | scanf("%d", &n); 53 | while (n--) 54 | { 55 | scanf("%s %s", s1, s2); 56 | l1 = strlen(s1); 57 | l2 = strlen(s2); 58 | memset(dp, 0x00, sizeof(dp)); 59 | for (int i = 0; i <= l1; i++) 60 | dp[i][0] = i; 61 | for (int j = 0; j <= l2; j++) 62 | dp[0][j] = j; 63 | for (int i = 1; i <= l1; i++) 64 | for (int j = 1; j <= l2; j++) 65 | dp[i][j] = min(dp[i - 1][j] + 1, min(dp[i][j - 1] + 1, dp[i - 1][j - 1] + (s1[i - 1] != s2[j - 1]))); 66 | printf("%.6f\n", 1. / (dp[l1][l2] + 1)); 67 | } 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /第四阶段编程练习1/最优路径.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 给定一个n*m的方格棋盘,第i行第j列的方格价值为W(i, j)。现在你从第一行的任选方格出发,可以选择向南、 5 | 向西或者向东走,但是不能重复经过相同的格子(即不能走回头路),一直到第n行的任意一个方格为止。 6 | 请你设计一条路径,使得从开始到结束所经过的所有方格的价值和最大。 7 | 8 | 关于输入 9 | 10 | 输入包含多组数据。 11 | 每组数据第一行为两个整数n和m(1<=n, m<=200),表示棋盘大小。下接一个n*m的整数矩阵,描述价值矩阵, 12 | W(i,j)在[-1000, 1000]之内。 13 | 14 | 关于输出 15 | 16 | 对于每一组数据,输出一个整数,表示最大的价值。 17 | 18 | 例子输入 19 | 20 | 2 1 21 | 100 22 | -101 23 | 4 4 24 | 1 -5 20 3 25 | 3 2 -50 20 26 | 3 3 3 3 27 | 9 -100 0 17 28 | 29 | 例子输出 30 | 31 | -1 32 | 66 33 | 34 | 提示信息 35 | 36 | 样例第二组数据最优路径是(1,3)-(1,4)-(2,4)-(3,4)-(3,3)-(4,3)-(4,4) 37 | *****/ 38 | 39 | #include 40 | #include 41 | using namespace std; 42 | 43 | #define MAX_N 300 44 | #define MIN_INT 0x80000000 45 | 46 | int n = 0, m = 0; 47 | int psum[MAX_N][MAX_N] = {0}; 48 | int dp[MAX_N][MAX_N] = {0}; 49 | 50 | int main() 51 | { 52 | int num = 0; 53 | while (cin >> n >> m) 54 | { 55 | for (int i = 1; i <= n; i++) 56 | for (int j = 1; j <= m; j++) 57 | { 58 | cin >> psum[i][j]; 59 | psum[i][j] += psum[i][j - 1]; 60 | } 61 | for (int i = 1; i <= n; i++) 62 | for (int j = 1; j <= m; j++) 63 | { 64 | dp[i][j] = MIN_INT; 65 | for (int k = 1; k <= m; k++) 66 | { 67 | num = psum[i][max(j, k)] - psum[i][min(j, k) - 1]; 68 | dp[i][j] = max(dp[i][j], dp[i - 1][k] + num); 69 | } 70 | } 71 | num = MIN_INT; 72 | for (int j = 1; j <= m; j++) 73 | num = max(num, dp[n][j]); 74 | cout << num << endl; 75 | } 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /第四阶段编程练习1/采药.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。 5 | 医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说: “孩子, 6 | 这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间, 7 | 在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。” 8 | 如果你是辰辰,你能完成这个任务吗? 9 | 10 | 关于输入 11 | 12 | 输入第一行有两个整数T(1 ≤ T ≤ 1000)和M(1 ≤ M ≤ 100),用一个空格隔开,T代表总共能够用 13 | 来采药的时间,M代表山洞里的草药的数目。接下来的M行每行包括两个在1到100之间(包括1和100)的整 14 | 数,分别表示采摘某株草药的时间和这株草药的价值。 15 | 16 | 关于输出 17 | 18 | 输出包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。 19 | 20 | 例子输入 21 | 22 | 70 3 23 | 71 100 24 | 69 1 25 | 1 2 26 | 27 | 例子输出 28 | 29 | 3 30 | *****/ 31 | 32 | #include 33 | #include 34 | using namespace std; 35 | 36 | #define MAX_N 110 37 | #define MAX_T 1010 38 | 39 | /** 40 | 思路 -- 动态规划 41 | 42 | 这是一道典型的背包问题--在若干价值和大小不同的物品里选择,使得有大小限制的背包装下的物品价值的和最高。 43 | 这道题目的草药价值对应物品价值,挖草药的用时对应物品大小,时间上限对应背包大小。 44 | 用dp[i][j]来记录前i个物体,用大小为j的背包,能装下的最高的价值和。显然dp[0][j] = 0。 45 | 假设dp[i-1][j]都是已知的,那么递推dp[i][j]时就有两种情况: 46 | 1. 第i件物品太大,装不进背包,那么dp[i][j] = dp[i-1][j]; 47 | 2. 第i件物品能装下,那么我们要么选择装(价值对应dp[i-1][j-size[i]]+val[i]),要么选择不装(价值对应dp[i-1][j])。 48 | 综上,我们可以从dp[1][1]开始,不断递推。最终dp[n_item][bag_size]即为所求答案。 49 | **/ 50 | 51 | int val[MAX_N] = {0}, _time[MAX_N] = {0}; 52 | int dp[MAX_N][MAX_T]={0}; 53 | 54 | int main() 55 | { 56 | int n = 0, t = 0; 57 | cin >> t >> n; 58 | for (int i = 1; i <= n; i++) 59 | cin >> _time[i] >> val[i]; 60 | for (int i = 1; i <= n; i++) 61 | for (int j = 1; j <= t; j++) 62 | if (_time[i] > j) 63 | dp[i][j] = dp[i - 1][j]; 64 | else 65 | dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - _time[i]] + val[i]); 66 | cout << dp[n][t] << endl; 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /2020年期末考试题/特殊素数序列.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 给丁一对正整数[p,q],其中,p小于q 且q不大于100000 5 | 请按从小到大的顺序输出p和q之间的素数序列,以逗号间隔。输出的素数 a 需满足如下二个条件: 6 | (1)p<=a<=q; 7 | (2)a 的逆序 b 也必须是素数,且 a<=b,同时,p<=b<=q 8 | 例如,p=2, q=50,则输出: 9 | 2,3,5,7,11,13 10 | 注意:13的逆序31也是素数,且都在[2,50]的范围内,13小于31,故只输出 13. 11 | 如果没有满足条件的序列,则输出 NULL 12 | 13 | 关于输入 14 | 15 | 两个正整数,由逗号间隔,分别表示 p 和 q 16 | 17 | 关于输出 18 | 19 | 输出符合条件的素数序列,其间以逗号间隔;如果没有满足条件的序列,则输出 NULL 20 | 21 | 例子输入 22 | 23 | 10,50 24 | 25 | 例子输出 26 | 27 | 11,13 28 | *****/ 29 | 30 | #include 31 | #include 32 | using namespace std; 33 | 34 | #define MAX_NUM 100100 35 | 36 | bool is_prime[MAX_NUM] = {false}; 37 | 38 | void gen_prime(int q) 39 | { 40 | memset(is_prime, 0xff, sizeof(is_prime)); 41 | is_prime[0] = is_prime[1] = false; 42 | for (int i = 2; i <= q; i++) 43 | if (is_prime[i]) 44 | for (int j = i + i; j <= q; j += i) 45 | is_prime[j] = false; 46 | } 47 | 48 | int rev_num(int n) 49 | { 50 | int ret = 0; 51 | while (n) 52 | { 53 | ret = ret * 10 + (n % 10); 54 | n /= 10; 55 | } 56 | return ret; 57 | } 58 | 59 | int main() 60 | { 61 | int p = 0, q = 0; 62 | char c = '\0'; 63 | bool flag = false; 64 | cin >> p >> c >> q; 65 | gen_prime(q); 66 | for (int i = p, j = p; i <= q; i++) 67 | { 68 | j = rev_num(i); 69 | if (is_prime[i] && is_prime[j] && i <= j && j <= q) 70 | { 71 | if (flag) 72 | cout << c; 73 | else 74 | flag = true; 75 | cout << i; 76 | } 77 | } 78 | if (flag) 79 | cout << endl; 80 | else 81 | cout << "NULL" << endl; 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /综合练习/山区建小学.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 政府在某山区修建了一条道路,恰好穿越总共m个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过 5 | 这条路来往。已知任意两个相邻的村庄之间的距离为di(为正整数),其中,0 < i < m。为了提高山区的文化素 6 | 质,政府又决定从m个村中选择n个村建小学(设 0 < n < = m < 500 )。请根据给定的m、n以及所有相邻村庄的 7 | 距离,选择在哪些村庄建小学,才使得所有村到最近小学的距离总和最小,计算最小值。 8 | 9 | 关于输入 10 | 11 | 第1行为m和n,其间用空格间隔 12 | 第2行为(m-1) 个整数,依次表示从一端到另一端的相邻村庄的距离,整数之间以空格间隔。 13 | 例如 14 | 10 3 15 | 2 4 6 5 2 4 3 1 3 16 | 表示在10个村庄建3所学校。第1个村庄与第2个村庄距离为2,第2个村庄与第3个村庄距离为4,第3个村庄与第4个 17 | 村庄距离为6,...,第9个村庄到第10个村庄的距离为3。 18 | 19 | 关于输出 20 | 21 | 各村庄到最近学校的距离之和的最小值。 22 | 23 | 例子输入 24 | 25 | 10 2 26 | 3 1 3 1 1 1 1 1 3 27 | 28 | 例子输出 29 | 30 | 18 31 | *****/ 32 | 33 | #include 34 | #include 35 | using namespace std; 36 | 37 | #define MAX_INT 0x7fffffff 38 | #define MAX_N 1000 39 | 40 | int m = 0, n = 0; 41 | int dist[MAX_N][MAX_N] = {0}; 42 | int total[MAX_N][MAX_N] = {0}; 43 | int dp[MAX_N][MAX_N] = {0}; 44 | 45 | int main() 46 | { 47 | cin >> m >> n; 48 | for(int i = 1; i < m; i++) 49 | cin>>dist[i][i+1]; 50 | 51 | for(int i = 1; i <= m; i++) 52 | for(int j = i + 1; j <= m; j++) 53 | dist[i][j] = dist[j][i] = dist[i][j - 1] + dist[j - 1][j]; 54 | for(int i = 1; i <= m; i++) 55 | for(int j = i + 1; j <= m; j++) 56 | { 57 | int mid = (i + j) / 2; 58 | for(int k = i; k <= j; k++) 59 | total[i][j] += dist[k][mid]; 60 | } 61 | 62 | for(int i = 1; i <= m; i++) 63 | dp[i][1] = total[1][i]; 64 | for(int i = 1; i <= m; i++) 65 | for(int j = 2; j <= n; j++) 66 | { 67 | dp[i][j] = MAX_INT; 68 | for(int k = j - 1;k <= i; k++) 69 | dp[i][j] = min(dp[i][j], dp[k][j - 1] + total[k + 1][i]); 70 | } 71 | cout << dp[m][n]; 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /2020年期末考试题/对角遍历.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 阿福最近在研究矩阵的遍历。给定一个大小为4nx4n的方阵,现在需要将序号0-4nx4n-1依次放入到 5 | 方阵中。放置方式具体如下: 6 | 首先,将4nx4n分成16个4n-1x4n-1的子块,然后按照对角遍历的方式(如下图所示)遍历各个子块; 7 | 对于每个子块继续划分成16个更小的子块,并按照如下图所示的方式遍历各个子块,..., 以此类推, 8 | 并将遍历的顺序号依次填入各个1x1方块中。 9 | 现在给定非负整数n,一个1x1方块的行号x和列号y,其中0<=x,y<4n,请求出该块遍历的序号。输入保证1<=n<=10。 10 | 11 | 关于输入 12 | 13 | 包含多行,每行三个非负整数n,x,y,中间用空格隔开 14 | 当n为0时,表示输入结束,该组输入不用处理 15 | 16 | 关于输出 17 | 18 | 输出包括多行,每行一个整数,表示输入块按照上述遍历方式得到的序号。 19 | 20 | 例子输入 21 | 22 | 2 3 3 23 | 4 4 4 24 | 5 12 9 25 | 0 1 2 26 | 27 | 例子输出 28 | 29 | 15 30 | 64 31 | 210 32 | *****/ 33 | 34 | #include 35 | #include 36 | using namespace std; 37 | 38 | #define BLOCK 4 39 | #define MAX_N 100 40 | 41 | int block[BLOCK][BLOCK] = 42 | { 43 | {0, 2, 5, 9}, // Traversal order 44 | {1, 4, 8, 12}, 45 | {3, 7, 11, 14}, 46 | {6, 10, 13, 15}, 47 | }; 48 | 49 | int main() 50 | { 51 | int n = 0, _max = 0; 52 | int xt = 0, yt = 0; 53 | int x = 0, y = 0; 54 | int st[MAX_N] = {0}, n_st = 0; 55 | int ans = 0; 56 | while (cin >> n >> x >> y) 57 | { 58 | if (!n) 59 | return 0; 60 | _max = pow(BLOCK, n); 61 | while (_max) // Unwrapping the folded blocks 62 | { 63 | xt = x / _max; 64 | yt = y / _max; 65 | if (n_st || block[xt][yt]) 66 | st[n_st++] = block[xt][yt]; // Store the block index (traversal order) in st 67 | x %= _max; 68 | y %= _max; 69 | _max /= BLOCK; 70 | } 71 | ans = 0; 72 | _max = 1; 73 | while (n_st) // Recover the value 74 | { 75 | ans += st[--n_st] * _max; 76 | _max *= BLOCK * BLOCK; 77 | } 78 | cout << ans << endl; 79 | } 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /第三阶段编程练习3/回数猜想.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 回数猜想: 任取一个数,再把它倒过来,并把这两个数相加,然后把这个和数再倒过来,与原和数相 5 | 加,重复此过程,一定能获得一个回数。例: 68 倒过来是 86 6 | 68+86= 154,154+451= 605, 605+506=1111 (回数) 7 | 编程,输入任意整数,按上述方法产生一个回数,为简便起见,最多计算7步,看是否能得到一个回数。 8 | 要求: 9 | 主函数中接收键盘数据,显示该数与其倒数的和,输出每一步计算步骤。 10 | 子函数1,计算该数的倒数。 11 | 子函数2,验证和是否为回数, 12 | 13 | 关于输入 14 | 15 | 输入为int型 16 | 17 | 关于输出 18 | 19 | 换行输出每步计算过程(最多七步) 20 | 输出7步内是否得到一个回数(Y/N) 21 | 22 | 例子输入 23 | 24 | 68 25 | 26 | 例子输出 27 | 28 | 68+86=154 29 | 154+451=605 30 | 605+506=1111 31 | Y 32 | *****/ 33 | 34 | #include 35 | #include 36 | #include 37 | using namespace std; 38 | 39 | #define MAX_LEN 100 40 | #define MAX_STEP 7 41 | 42 | char s[MAX_LEN] = "", r[MAX_LEN] = ""; 43 | 44 | /** 生成n的倒序字符串 **/ 45 | void get_reverse(int n) 46 | { 47 | sprintf(s, "%d", n); 48 | strcpy(r, s); 49 | reverse(r, r + strlen(r)); 50 | } 51 | 52 | /** 判断n是否回文 **/ 53 | bool is_palindromic(int n) 54 | { 55 | get_reverse(n); 56 | if (!strcmp(s, r)) 57 | return true; 58 | return false; 59 | } 60 | 61 | int main() 62 | { 63 | int num = 0, n = 0, rev_num = 0; 64 | scanf("%d", &num); 65 | while (n++ < MAX_STEP) 66 | { 67 | if (is_palindromic(num)) // 若num回文 68 | { 69 | printf("Y\n"); // 则输出Y 70 | return 0; // 函数直接返回 71 | } 72 | sscanf(r, "%d", &rev_num); // 将r中倒序字符串转为int类型存放在rev_num中 73 | printf("%d+%d=%d\n", num, rev_num, num + rev_num); // 打印计算步骤 74 | num += rev_num; // 更新num 75 | } 76 | if (is_palindromic(num)) // 判断num是否回文 77 | { 78 | printf("Y\n"); 79 | return 0; 80 | } 81 | printf("N\n"); // 无法在MAX_STEP内完成,输出N 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /第三阶段编程练习3/排队游戏.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 在幼儿园中,老师安排小朋友做一个排队的游戏。首先老师精心的把数目相同的小男孩和小女孩编排在一个队列中, 5 | 每个小孩按其在队列中的位置发给一个编号(编号从0开始)。然后老师告诉小朋友们,站在前边的小男孩可以和他 6 | 后边相邻的小女孩手拉手离开队列,剩余的小朋友重新站拢,再按前后相邻的小男孩小女孩手拉手离开队列游戏,如 7 | 此往复。由于教师精心的安排,恰好可以保证每两个小朋友都能手拉手离开队列,并且最后离开的两个小朋友是编号 8 | 最小的和最大的两个小朋友。(注:只有小男孩在前,小女孩在后,且他们两之间没有其他的小朋友,他们才能手拉 9 | 手离开队列)。请根据老师的排队,按小女孩编号从小到大的顺序,给出所有手拉手离开队列的小男孩和小女孩的编 10 | 号对。 11 | 12 | 关于输入 13 | 14 | 用一个字符串代表小朋友队列。字符串中只会出现两个字符,分别代表小男孩和小女孩,首先出现的字符代表小男孩, 15 | 另一个字符代表小女孩。小孩总数不超过100 16 | 注意:只会出现两个字符不代表只会出现括号() 17 | 18 | 关于输出 19 | 20 | 按小女孩编号顺序,顺序输出手拉手离开队列的小男孩和小女孩的编号对,每行一对编号,编号之间用一个空格分隔。 21 | 22 | 例子输入 23 | 24 | ((()(())())(())) 25 | 26 | 例子输出 27 | 28 | 2 3 29 | 5 6 30 | 4 7 31 | 8 9 32 | 1 10 33 | 12 13 34 | 11 14 35 | 0 15 36 | *****/ 37 | 38 | #include 39 | using namespace std; 40 | 41 | /** 42 | 思路 43 | 44 | 我们使用一种叫做栈(stack)的数据结构来解这道题。栈只能从一端放入(push)或者取出(pop),其性质为后进先出。 45 | 举个例子,假设我们读到'('就push,读到')'就pop,那么对于输入的字符串"()(())()",栈的状态变化如下: 46 | Stack Action InputChar 47 | ( Push ( 48 | 空 Pop ) 49 | ( Push ( 50 | (( Push ( 51 | ( Pop ) 52 | 空 Pop ) 53 | ( Push ( 54 | 空 Pop ) 55 | 栈可以很方便地帮助我们解决括号匹配一类的问题,也可以认为栈是解决这一类问题的标准做法。 56 | 这道题,我们可以维护一个栈,每当遇到左括号就push当前下标入栈,每当遇到有括号就pop并输出。 57 | **/ 58 | 59 | #define MAX_LEN 110 60 | int st[MAX_LEN] = {0}, n_st = 0; 61 | 62 | int main() 63 | { 64 | char c = 0, lc = 0, rc = 0; 65 | for (int i = 0; ; i++) 66 | { 67 | cin.get(c); 68 | if (c == '\n') 69 | break; 70 | if (!lc) 71 | lc = c; 72 | if (!rc && lc && lc != c) 73 | rc = c; 74 | if (c == lc) 75 | st[n_st++] = i; // Push 76 | else 77 | cout << st[--n_st] << " " << i << endl; // Pop & output 78 | } 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /综合练习/Unix纪元.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 在著名的unix系统中,使用了一种简洁高效的时间表示方法,即: 5 | 将1970年1月1日0点作为“unix纪元”的原点,从1970年1月1日开始经过的秒数存储为一个32位整数 6 | 请编写一个程序,帮助把一个unix时间辍,转换成形如"YYYY-mm-dd HH:ii:ss"的格式,其中的字母分别代表 7 | YYYY 4 位数字完整表示的年份 8 | mm 数字表示的月份,有前导零的 2 位数字 9 | dd 月份中的第几天,有前导零的2位数字 10 | HH 小时,24 小时格式,有前导零 11 | ii 有前导零的分钟数 12 | ss 秒数,有前导零 13 | 14 | 关于输入 15 | 16 | 输入数据有若干行,每行包含一个整数t,(0<=t<2^31) 17 | 18 | 关于输出 19 | 20 | 对每一行输入数据,输出一行,为形如“YYYY-mm-dd HH:ii:ss”格式的时间 21 | 22 | 例子输入 23 | 24 | 10 25 | 1234567890 26 | 27 | 例子输出 28 | 29 | 1970-01-01 00:00:10 30 | 2009-02-13 23:31:30 31 | *****/ 32 | 33 | #include 34 | 35 | #define N_MONTH 12 36 | #define MINUTE_SEC 60 37 | #define HOUR_SEC (60 * 60) 38 | #define DAY_SEC (24 * 60 * 60) 39 | 40 | int month[2][N_MONTH + 1] = 41 | { 42 | {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 43 | {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 44 | }; 45 | int year[2] = {365, 366}; 46 | 47 | int is_leap(int y) 48 | { 49 | if (((y % 100) && !(y % 4)) || !(y % 400)) 50 | return 1; 51 | return 0; 52 | } 53 | 54 | int main() 55 | { 56 | unsigned int t = 0; 57 | int ss = 0, ii = 0, hh = 0, dd = 0, mm = 0, yyyy = 0; 58 | int days = 0, secs = 0; 59 | while (scanf("%u", &t) != EOF) 60 | { 61 | days = t / DAY_SEC; 62 | secs = t % DAY_SEC; 63 | ss = secs % MINUTE_SEC; 64 | ii = (secs % HOUR_SEC) / MINUTE_SEC; 65 | hh = secs / HOUR_SEC; 66 | yyyy = 1970; 67 | for (yyyy = 1970; days >= year[is_leap(yyyy)]; days -= year[is_leap(yyyy)], yyyy++); 68 | for (mm = 1; days >= month[is_leap(yyyy)][mm]; days -= month[is_leap(yyyy)][mm], mm++); 69 | dd = days + 1; 70 | printf("%d-%02d-%02d %02d:%02d:%02d\n", yyyy, mm, dd, hh, ii, ss); 71 | } 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /2020年期末考试题/DNA排序.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 作为医学生的你,一定对DNA不陌生。DNA可以看作是由字母'A''C''G''T'组成的字符串,现在有一些DNA序列需要你排序, 5 | 排序的规则是按照DNA序列中逆序对的个数。逆序对的定义就是字符串中,在字母表中靠后的字母排在了字母表中靠前的字母 6 | 的前面。举例来说,字符串"DAABEC"的逆序对数为5,分别是"D-A""D-A""D-B","D-C"和"E-C",而"AACEDGG'' 就只有"C-E" 7 | 这一个逆序对,"ABCDE"就没有逆序对。现在,给你一些DNA序列,请你将它们按照逆序对的个数从小到大排序。 8 | 9 | 关于输入 10 | 11 | 第一行是两个整数n和m,0 37 | #include 38 | using namespace std; 39 | 40 | #define MAX_LEN 60 41 | #define MAX_M 110 42 | 43 | struct DNA 44 | { 45 | char s[MAX_LEN]; 46 | int cnt; 47 | } dna[MAX_M] = {{"\0", 0}}; 48 | 49 | int main() 50 | { 51 | int n = 0, m = 0; 52 | char buf[MAX_LEN] = "\0"; 53 | cin >> n >> m; 54 | for (int i = 0; i < m; i++) 55 | { 56 | cin >> dna[i].s; 57 | for (int j = 1; j < n; j++) 58 | for (int k = 0; k < j; k++) 59 | if (dna[i].s[j] < dna[i].s[k]) 60 | dna[i].cnt++; 61 | } 62 | for (int i = 1; i < m; i++) 63 | for (int j = 0; j < i; j++) 64 | if (dna[i].cnt < dna[j].cnt) 65 | { 66 | strcpy(buf, dna[i].s); 67 | strcpy(dna[i].s, dna[j].s); 68 | strcpy(dna[j].s, buf); 69 | dna[i].cnt ^= dna[j].cnt; 70 | dna[j].cnt ^= dna[i].cnt; 71 | dna[i].cnt ^= dna[j].cnt; 72 | } 73 | for (int i = 0; i < m; i++) 74 | cout << dna[i].s << endl; 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /第四阶段编程练习2/Unix纪元.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 在著名的unix系统中,使用了一种简洁高效的时间表示方法,即: 5 | 将1970年1月1日0点作为“unix纪元”的原点,从1970年1月1日开始经过的秒数存储为一个32位整数 6 | 请编写一个程序,帮助把一个unix时间辍,转换成形如"YYYY-mm-dd HH:ii:ss"的格式,其中的字母分别代表 7 | YYYY 4 位数字完整表示的年份 8 | mm 数字表示的月份,有前导零的 2 位数字 9 | dd 月份中的第几天,有前导零的2位数字 10 | HH 小时,24 小时格式,有前导零 11 | ii 有前导零的分钟数 12 | ss 秒数,有前导零 13 | 14 | 关于输入 15 | 16 | 输入数据有若干行,每行包含一个整数t,(0<=t<2^31) 17 | 18 | 关于输出 19 | 20 | 对每一行输入数据,输出一行,为形如“YYYY-mm-dd HH:ii:ss”格式的时间 21 | 22 | 例子输入 23 | 24 | 10 25 | 1234567890 26 | 27 | 例子输出 28 | 29 | 1970-01-01 00:00:10 30 | 2009-02-13 23:31:30 31 | *****/ 32 | 33 | #include 34 | 35 | #define N_MONTH 12 36 | #define MINUTE_SEC 60 37 | #define HOUR_SEC (60 * 60) 38 | #define DAY_SEC (24 * 60 * 60) 39 | 40 | int month[2][N_MONTH + 1] = 41 | { 42 | {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 43 | {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 44 | }; 45 | int year[2] = {365, 366}; 46 | 47 | int is_leap(int y) 48 | { 49 | if (((y % 100) && !(y % 4)) || !(y % 400)) 50 | return 1; 51 | return 0; 52 | } 53 | 54 | int main() 55 | { 56 | unsigned int t = 0; 57 | int ss = 0, ii = 0, hh = 0, dd = 0, mm = 0, yyyy = 0; 58 | int days = 0, secs = 0; 59 | while (scanf("%u", &t) != EOF) 60 | { 61 | days = t / DAY_SEC; 62 | secs = t % DAY_SEC; 63 | ss = secs % MINUTE_SEC; 64 | ii = (secs % HOUR_SEC) / MINUTE_SEC; 65 | hh = secs / HOUR_SEC; 66 | yyyy = 1970; 67 | for (yyyy = 1970; days >= year[is_leap(yyyy)]; days -= year[is_leap(yyyy)], yyyy++); 68 | for (mm = 1; days >= month[is_leap(yyyy)][mm]; days -= month[is_leap(yyyy)][mm], mm++); 69 | dd = days + 1; 70 | printf("%d-%02d-%02d %02d:%02d:%02d\n", yyyy, mm, dd, hh, ii, ss); 71 | } 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /第四阶段编程练习1/矩阵乘法(使用指针完成).cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 计算两个矩阵的乘法。n*m阶的矩阵A乘以m*k阶的矩阵B得到的矩阵C是n*k阶的,且 5 | C[i][j] = A[i][0]*B[0][j] + A[i][1]*B[1][j] + …… +A[i][m-1]*B[m-1][j] 6 | (C[i][j]表示C矩阵中第i行第j列元素) 7 | 8 | 关于输入 9 | 10 | 首先输入G,即测试数据的组数 11 | 每组测试数据输入: 12 | 第一行为n, m, k,表示A矩阵是n行m列,B矩阵是m行k列,n, m, k均小于100 13 | 然后先后输入A和B两个矩阵,A矩阵n行m列,B矩阵m行k列,矩阵中每个元素不会大 14 | 于10000 15 | 16 | 关于输出 17 | 18 | 针对每组数据,输出n行k列的C矩阵 19 | 20 | 例子输入 21 | 22 | 1 23 | 3 2 3 24 | 1 1 25 | 1 1 26 | 1 1 27 | 1 1 1 28 | 1 1 1 29 | 30 | 例子输出 31 | 32 | 2 2 2 33 | 2 2 2 34 | 2 2 2 35 | 36 | 提示信息 37 | 38 | 注意每行最后一个数后边的空格不要输出 39 | *****/ 40 | 41 | #include 42 | using namespace std; 43 | 44 | int main() 45 | { 46 | int n_case = 0; 47 | int n = 0, m = 0, k = 0; 48 | int **A = NULL, **B = NULL, C = 0; 49 | cin >> n_case; 50 | while (n_case--) 51 | { 52 | cin >> n >> m >> k; 53 | 54 | /** 给指针分配空间 **/ 55 | A = new int*[n]; 56 | for (int i = 0; i < n; i++) 57 | A[i] = new int[m]; 58 | B = new int*[m]; 59 | for (int i = 0; i < m; i++) 60 | B[i] = new int[k]; 61 | 62 | /** 读入数据 **/ 63 | for (int i = 0; i < n; i++) 64 | for (int j = 0; j < m; j++) 65 | cin >> A[i][j]; 66 | for (int i = 0; i < m; i++) 67 | for (int j = 0; j < k; j++) 68 | cin >> B[i][j]; 69 | 70 | /** 计算结果的各个元素并输出 **/ 71 | for (int i = 0; i < n; i++) 72 | for (int j = 0; j < k; j++) 73 | { 74 | C = 0; 75 | for (int l = 0; l < m; l++) 76 | C += A[i][l] * B[l][j]; 77 | cout << C; 78 | if (j == k - 1) 79 | cout << endl; 80 | else 81 | cout << " "; 82 | } 83 | } 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /2021年期末考试题/盗宝.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 有个财主收藏了大量的宝物。为防止被盗,他将宝物藏在离家不太远一个海岛上的不同洞穴内,有些洞内放 5 | 了一件宝物,有些洞存放了多件,并绘制了藏宝图。但藏宝图不慎被一个海盗发现,他详细知道了每件宝物 6 | 所在的洞穴。好在财主事先做了进一步的防范措施:万一有人进入一个洞内窃取宝物,最多只能取走洞内的 7 | 一件宝物,而且不能让其再进入同一个洞内。海盗决定驾着他的小船去盗宝,但船承载货物的重量受限。已 8 | 知每件宝物的重量和价值,请你根据船的载重量,推算海盗在每个洞只能进去一次的情况下,这一趟盗走宝 9 | 物可能导致财主最大价值的损失是多少? 10 | 11 | 关于输入 12 | 13 | 第一行两个整数m,n(1<=m,n<=1000),分别是船的载货重量(海盗自身的重量忽略不计)和宝物总件数。 14 | 两个整数以空格间隔 15 | 接下来n行,每行3个数,分别表示各件宝物的重量、价值和所在洞的编号。均为整数,且以空格间隔。 16 | 17 | 关于输出 18 | 19 | 一个整数值,为所盗宝物可能的最大总价值。 20 | 21 | 例子输入 22 | 23 | 30 3 24 | 15 8 1 25 | 10 5 1 26 | 48 400 2 27 | 28 | 例子输出 29 | 30 | 8 31 | *****/ 32 | 33 | #include 34 | #include 35 | using namespace std; 36 | 37 | #define MAX_C 10000 38 | #define MAX_N 10000 39 | 40 | int w[MAX_C][MAX_N] = {0}; // w[i][j] weight of j-th treasure in i-th cave 41 | int v[MAX_C][MAX_N] = {0}; // v[i][j] value of j-th treasure in i-th cave 42 | int cave[MAX_N] = {0}; // Treasure number in each cave 43 | int dp[MAX_C][MAX_N] = {0}; 44 | 45 | int main() 46 | { 47 | int m = 0, n = 0; 48 | int max_cave = 0; 49 | int a= 0, b = 0, c = 0; 50 | cin >> m >> n; 51 | for (int i = 0; i < n; i++) 52 | { 53 | cin >> a >> b >> c; 54 | max_cave = max(max_cave, c); 55 | w[c][cave[c]] = a; 56 | v[c][cave[c]] = b; 57 | cave[c]++; 58 | } 59 | 60 | /** Init **/ 61 | for (int i = 1; i <= max_cave; i++) 62 | for (int j = 0; j < cave[i]; j++) 63 | for (int k = w[i][j]; k <= m; k++) 64 | dp[i][k] =max(v[i][j], dp[i][k]); 65 | 66 | /** DP **/ 67 | for (int i = 0; i <= m; ++i) 68 | for (int j = 1; j <= max_cave; ++j) 69 | for (int k = 0; k < cave[j]; ++k) 70 | if (i >= w[j][k]) 71 | { 72 | dp[j][i] = max(dp[j][i], dp[j - 1][i - w[j][k]] + v[j][k]); 73 | dp[j][i] = max(dp[j][i], dp[j - 1][i]); 74 | } 75 | else 76 | dp[j][i] = max(dp[j - 1][i],dp[j][i]); 77 | cout << dp[max_cave][m] << endl; 78 | } 79 | -------------------------------------------------------------------------------- /综合练习/求最长回文子串.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 给定一个串S,长度小于等于100000,求S的最长回文子串的长度(回文串是指一个串正序和逆序相同)。 5 | 6 | 关于输入 7 | 8 | 给定的字符串S 9 | 10 | 关于输出 11 | 12 | 一个数,表示最长回文子串的长度 13 | 14 | 例子输入 15 | 16 | aaabbac 17 | 18 | 例子输出 19 | 20 | 4 21 | 22 | 提示信息 23 | 24 | 暴力会超时,用分治吧 25 | *****/ 26 | 27 | #include 28 | #include 29 | #include 30 | using namespace std; 31 | 32 | #define MAX_N 1001000 33 | 34 | const int P = 131; 35 | char str[MAX_N]; 36 | unsigned long long h1[MAX_N], h2[MAX_N], p[MAX_N]; 37 | 38 | unsigned long long hash1(int l, int r) 39 | { 40 | return h1[r] - h1[l - 1] * p[r - l + 1]; 41 | } 42 | 43 | unsigned long long hash2(int l, int r) 44 | { 45 | return h2[l] - h2[r + 1] * p[r - l + 1]; 46 | } 47 | 48 | int main() 49 | { 50 | cin >> str + 1; 51 | int len = strlen(str + 1); 52 | 53 | h1[0] = 0; 54 | for(int i = 1; i <= len; i++) 55 | h1[i] = h1[i - 1] * P + (str[i] - 'a' + 1); 56 | h2[len + 1] = 0; 57 | for(int i = len; i >= 1; i--) 58 | h2[i] = h2[i + 1] * P + (str[i] - 'a' + 1); 59 | p[0] = 1; 60 | for(int i = 1;i < MAX_N; i++) 61 | p[i] = p[i - 1] * P; 62 | 63 | int ans = 0; 64 | for(int i = 1; i <= len; i++) 65 | { 66 | int l = 0, r = min(i - 1, len - i); 67 | while(l < r) 68 | { 69 | int mid = (l + r + 1) / 2; 70 | if(hash1(i - mid, i - 1) == hash2(i + 1, i + mid)) 71 | l = mid; 72 | else 73 | r = mid - 1; 74 | } 75 | ans=max(ans, l + l + 1); 76 | 77 | l = 0; 78 | r = min(i - 1, len - i + 1); 79 | while(l < r) 80 | { 81 | int mid = (l + r + 1) / 2; 82 | if(hash1(i - mid, i - 1) == hash2(i, i + mid - 1)) 83 | l = mid; 84 | else r = mid - 1; 85 | } 86 | ans = max(ans, l + l); 87 | } 88 | cout << ans << endl; 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /2020年期末考试题/球桌出租.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 某乒乓球场里有很多张球桌,其中有一张由极品材料制作而成,大家都喜欢租这张球桌打球。 5 | 由于租的人太多,每年开张第一天,这张球桌的订单就如雪片一样飞来。这些订单中预订的时 6 | 间从开张第一天一直到过年关门的那一天都有,更让老板为难的是:这些订单中总是有很多 7 | 的时间冲突,接受了一张订单可能就有好些订单必须得拒绝。 8 | 现在,老板又在为这些订单犯愁了,某人很不厚道地向他透露了你精通动态规划算法的消息, 9 | 于是老板二话没说把订单全扔给了你,请你为他选择接受一些订单使得获益最大。 10 | 对你来说,小菜一碟,不是么?:) 11 | 12 | 关于输入 13 | 14 | 第一行是一个正整数n(1<=n<=100000),表示订单的数目。 15 | 接下来n行,每行表示一份订单,包含三个非负整数s,t和c,其中s,t表示订单预订的时间段 16 | 及从时刻s到时刻t(0 <= s < t < = 2100000000),c表示客户愿意为这份订单出多少钱。 17 | 18 | 关于输出 19 | 20 | 输出只包含一个整数,表示采用最优方案时老板能够获益多少(答案不超过32位有符号整数所 21 | 能表示的范围)。 22 | 23 | 例子输入 24 | 25 | 3 26 | 0 2 2 27 | 2 4 4 28 | 1 3 5 29 | 30 | 例子输出 31 | 32 | 6 33 | 34 | 提示信息 35 | 36 | 对于样例:接受第1份和第2份订单,获益是6,如果接受第3份订单,获益是5,所以答案应该是6 37 | 本题时间复杂度应为O(nlogn) 38 | *****/ 39 | 40 | #include 41 | #include 42 | using namespace std; 43 | 44 | #define MAX_N 100100 45 | #define MAX_INT 0x7fffffff 46 | 47 | struct Range 48 | { 49 | int l; 50 | int r; 51 | int v; 52 | } o[MAX_N]; 53 | int n = 0, dp[MAX_N] = {0}; 54 | 55 | bool cmp(Range &a, Range &b) 56 | { 57 | if (a.r == b.r) 58 | return a.l < b.l; 59 | return a.r < b.r; 60 | } 61 | 62 | int bin_search(int st, int l, int r) // Binary search 63 | { 64 | int m = (l + r) / 2; 65 | if (o[m].r <= st && o[m + 1].r > st) 66 | return m; 67 | if (l == m || o[m].r <= st) 68 | return bin_search(st, m + 1, r); 69 | return bin_search(st, l, m - 1); 70 | } 71 | 72 | int main() 73 | { 74 | int ans = 0, idx = 0; 75 | cin >> n; 76 | for (int i = 1; i <= n; i++) 77 | cin >> o[i].l >> o[i].r >> o[i].v; 78 | sort(o + 1, o + n + 1, cmp); // O(n log n) 79 | for (int i = 1;i <= n; i++) 80 | { 81 | idx = bin_search(o[i].l, 0, i); // O(log n), repeat n times. Therefore O(n log n) 82 | dp[i] = max(dp[i - 1], dp[idx] + o[i].v); 83 | ans = max(ans, dp[i]); 84 | } 85 | cout << ans << endl; 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /2021年期末考试题/城堡问题.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 图1是一个城堡的地形图。请你编写一个程序,计算城堡一共有多少房间,最大的房间有多大。城堡被分割成 5 | m*n(m≤50,n≤50)个方块,每个方块可以有0~4面墙。 6 | 7 | 关于输入 8 | 9 | 程序从标准输入设备读入数据。第一行是两个整数,分别是南北向、东西向的方块数。在接下来的输入行里, 10 | 每个方块用一个数字(0≤p≤50)描述。用一个数字表示方块周围的墙,1表示西墙,2表示北墙,4表示东墙, 11 | 8表示南墙。每个方块用代表其周围墙的数字之和表示。城堡的内墙被计算两次,方块(1,1)的南墙同时也是 12 | 方块(2,1)的北墙。输入的数据保证城堡至少有两个房间。 13 | 14 | 关于输出 15 | 16 | 输出分为两行。城堡的房间数、城堡中最大房间所包括的方块数。结果显示在标准输出设备上。 17 | 18 | 例子输入 19 | 20 | 4 7 21 | 11 6 11 6 3 10 6 22 | 7 9 6 13 5 15 5 23 | 1 10 12 7 13 7 5 24 | 13 11 10 8 10 12 13 25 | 26 | 例子输出 27 | 28 | 5 29 | 9 30 | *****/ 31 | 32 | #include 33 | #include 34 | #include 35 | using namespace std; 36 | 37 | #define MAX_N 100 38 | #define ND 4 39 | #define MASK -1 40 | 41 | int arr[MAX_N][MAX_N] = {0}; 42 | int n_row = 0, n_col = 0; 43 | const int dr[ND] = {0, -1, 0, 1}; // West, North, East, South 44 | const int dc[ND] = {-1, 0, 1, 0}; 45 | int n_mask = 0, prev_n_mask = 0; 46 | 47 | bool is_wall(int v, int d) 48 | { 49 | return v & (1 << d); 50 | } 51 | 52 | void dfs(int r, int c) 53 | { 54 | int v = arr[r][c]; 55 | if (v == MASK) 56 | return ; 57 | arr[r][c] = MASK; 58 | n_mask++; 59 | for (int d = 0; d < ND; d++) 60 | if (!is_wall(v, d)) 61 | dfs(r + dr[d], c + dc[d]); 62 | } 63 | 64 | int main() 65 | { 66 | int cnt = 0, max_area = 0; 67 | memset(arr, 0xff, sizeof(arr)); 68 | cin >> n_row >> n_col; 69 | for (int i = 1; i <= n_row; i++) 70 | for (int j = 1; j <= n_col; j++) 71 | cin >> arr[i][j]; 72 | for (int i = 1; i <= n_row; i++) 73 | for (int j = 1; j <= n_col; j++) 74 | if (arr[i][j] != MASK) 75 | { 76 | dfs(i, j); 77 | cnt++; 78 | max_area = max(max_area, n_mask - prev_n_mask); 79 | prev_n_mask = n_mask; 80 | } 81 | cout << cnt << endl << max_area << endl; 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /第三阶段编程练习4/子集合划分.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 将一个没有重复元素的集合A分成若干个非空子集,使得A中每个元素属于且仅属于一个子集, 4 | 那么这些子集构成的集合称为A的一个划分。现在给定集合的元素个数n,希望知道有多少种不 5 | 同的划分(假定集合本身属于一种划分),当n=0的时候,也认为有一种划分。 6 | 例如,n=3 时,A={1,2,3}的所有划分如下: 7 | { {1} , {2} , {3} } 8 | { {1 , 2} , {3} } 9 | { {1 , 3} , {2} } 10 | { {1} , {2 , 3} } 11 | { {1 , 2 , 3} } 12 | 一共有5种。 13 | 14 | 关于输入 15 | 16 | 若干行整数,每行一个整数n,当为-1时结束 17 | 18 | 关于输出 19 | 20 | 每行对应的集合划分数(假设可以用long表示) 21 | 22 | 例子输入 23 | 24 | 0 25 | 3 26 | 13 27 | -1 28 | 29 | 例子输出 30 | 31 | 1 32 | 5 33 | 27644437 34 | *****/ 35 | 36 | #include 37 | using namespace std; 38 | 39 | #define MAX_N 300 40 | 41 | /** 42 | 思路 43 | 44 | 使用动态规划(dp),用二维数组dp来记录状态。 45 | dp[i][j]表示将i个不同的元素分成j个集合的划分方法数。 46 | 47 | 显然有 48 | dp[0][0] = 1 49 | dp[1][0] = 0 50 | dp[1][1] = 1 51 | ... 52 | 53 | 进一步,可以发现有如下递推关系 54 | dp[i][j] = = dp[i - 1][j - 1] + j * dp[i - 1][j], i > 1 and 0 < j <= i 55 | 在i-1个元素的划分数已知的前提下,将i个元素分成j个集合,其实就是如何将多出来的元素划分的问题 56 | 有两种情况: 57 | 1. 多出来的元素自己成为一个新的集合,其它i-1个元素分成j-1个集合(即dp[i-1][j-1]) 58 | 2. 多出来的元素进入已有的一个集合,其它i-1个元素分成j个集合,而多出来的元素进入这j个集合中的哪一个都可以(即j*dp[i-1][j]) 59 | **/ 60 | 61 | long long dp[MAX_N][MAX_N]={{1}, {0, 1}}; // dp数组 62 | int n_dp = 2; // n_dp表示当前还没有计算的最小的元素数 63 | 64 | int main() 65 | { 66 | int n = 0; 67 | int ans = 0; 68 | while(cin >> n) 69 | { 70 | if(n < 0) // 退出 71 | return 0; 72 | ans = 0; 73 | if (n >= n_dp) // 若n大于等于n_dp,说明dp没有覆盖住n,那么就需要继续计算dp 74 | { 75 | for(int i = n_dp; i <= n; i++) // 从上向下 76 | for(int j = 1;j <= i; j++) // 从左到右 77 | dp[i][j] = dp[i - 1][j - 1] + j * dp[i - 1][j]; // 计算dp 78 | n_dp = n; // 更新n_dp 79 | } 80 | for(int i = 0; i <= n; i++) // 将dp[n]整行相加 81 | ans = ans + dp[n][i]; // 得到所有划分数 82 | cout << ans << endl; 83 | } 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /第三阶段编程练习5/元素和最大的子矩阵.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 输入一个n级方阵,请找到此矩阵的一个子矩阵,此子矩阵的各个元素的和是所有子矩阵中最大的,输出这个子矩阵及这个最大的和。 5 | 6 | 关于输入 7 | 8 | 首先输入方阵的级数n, 9 | 然后输入方阵中各个元素。 10 | 11 | 关于输出 12 | 13 | 输出子矩阵, 14 | 最后一行输出这个子矩阵的元素的和。 15 | 16 | 例子输入 17 | 18 | 4 19 | 0 -2 -7 0 20 | 9 2 -6 2 21 | -4 1 -4 1 22 | -1 8 0 -2 23 | 24 | 例子输出 25 | 26 | 9 2 27 | -4 1 28 | -1 8 29 | 15 30 | *****/ 31 | 32 | #include 33 | using namespace std; 34 | 35 | #define MAX_N 1000 36 | #define MIN_INT 0x80000000 37 | 38 | int arr[MAX_N][MAX_N] = {0}; 39 | int sum[MAX_N][MAX_N] = {0}; // sum[i][j]存放arr[i][j]左上方的子矩阵的和(包括arr[i][j]点) 40 | int n = 0; 41 | 42 | int main() 43 | { 44 | int st_r = 0, st_c = 0, end_r = 0, end_c = 0, max_sum = MIN_INT; 45 | int num = 0; 46 | cin >> n; 47 | for (int i = 1; i <= n; i++) 48 | for (int j = 1; j <= n; j++) 49 | { 50 | cin >> arr[i][j]; 51 | sum[i][j] = sum[i][j - 1] + arr[i][j]; 52 | } 53 | for (int i = 1; i <= n; i++) 54 | for (int j = 1; j <= n; j++) 55 | sum[i][j] += sum[i - 1][j]; 56 | for (int r = 0; r < n; r++) 57 | for (int c = 0; c < n; c++) 58 | for (int _r = r + 1; _r <= n; _r++) 59 | for (int _c = c + 1; _c <= n; _c++) 60 | { 61 | num = sum[_r][_c] - sum[r][_c] - sum[_r][c] + sum[r][c]; // 左上点为arr[r+1][j+1],右下点为arr[i][j]的子矩阵的和 62 | if (num > max_sum) 63 | { 64 | st_r = r + 1; 65 | st_c = c + 1; 66 | end_r = _r; 67 | end_c = _c; 68 | max_sum = num; 69 | } 70 | } 71 | for (int i = st_r; i <= end_r; i++) 72 | { 73 | cout << arr[i][st_c]; 74 | for (int j = st_c + 1; j <= end_c; j++) 75 | cout << " " << arr[i][j]; 76 | cout << endl; 77 | } 78 | cout << max_sum << endl; 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /第三阶段编程练习4/八皇后.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋 5 | 盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。 6 | 对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b1b2...b8,其中bi为相应摆法中 7 | 第i行皇后所处的列数。已经知道8皇后问题一共有92组解(即92个不同的皇后串)。 8 | 给出一个数b,要求输出第b个串。串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时 9 | 比y小 10 | 11 | 关于输入 12 | 13 | 第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数b(1 <= b <= 92) 14 | 15 | 关于输出 16 | 17 | n行,每行输出对应一个输入。输出应是一个正整数,是对应于b的皇后串 18 | 19 | 例子输入 20 | 21 | 2 22 | 1 23 | 92 24 | 25 | 例子输出 26 | 27 | 15863724 28 | 84136275 29 | *****/ 30 | 31 | #include 32 | using namespace std; 33 | 34 | #define MAX_B 100 35 | #define N_BOARD 8 36 | 37 | int b[MAX_B] = {0}, n_b = 0; // 皇后串 38 | int board[N_BOARD][N_BOARD] = {0}; // 记录各个位置是否会被吃的棋盘,非0表示会,0表示不会 39 | 40 | void set_board(int row, int col, int val) // 设置棋盘,将(row, col)位置放上后,并将其左下、下、右下的所有格子加1 41 | { 42 | board[row][col] += val; 43 | for (int i = row + 1; i < N_BOARD; i++) 44 | board[i][col] += val; 45 | for (int i = row + 1, j = col - 1; i < N_BOARD && j >= 0; i++, j--) 46 | board[i][j] += val; 47 | for (int i = row + 1, j = col + 1; i < N_BOARD && j < N_BOARD; i++, j++) 48 | board[i][j] += val; 49 | } 50 | 51 | /** 深度优先搜索,产生所有的皇后串 **/ 52 | void dfs(int depth, int curr_b) 53 | { 54 | if (depth >= N_BOARD) // 深度超过棋盘 55 | { 56 | b[n_b++] = curr_b; // 搜索到一个皇后串,在b中记录 57 | return; 58 | } 59 | curr_b *= 10; // curr_b向左移一位(十进制) 60 | curr_b++; // 加一,因为皇后串的下标需要从1开始 61 | for (int i = 0; i < N_BOARD; i++) 62 | if (!board[depth][i]) // 若当前位置可以放置一个皇后 63 | { 64 | set_board(depth, i, 1); // 设置棋盘 65 | dfs(depth + 1, curr_b + i); // 向下深搜 66 | set_board(depth, i, -1); // 棋盘回溯 67 | } 68 | } 69 | 70 | int main() 71 | { 72 | int n = 0, m = 0; 73 | dfs(0, 0); 74 | cin >> n; 75 | while (n--) 76 | { 77 | cin >> m; 78 | cout << b[m - 1] << endl; 79 | } 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /综合练习/缩小积木.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 考完计算概论B后,阿福开始浪的飞起.最近阿福发现一个有趣的游戏.在他的面前有n个积木,从左至右每 5 | 个积木的高度为Hi,其中Hi为正整数,1 ≤ i ≤ n, 现在他想要用高度较小的积木来重新搭建该图形, 6 | 同时还要保持原图形中相邻积木高度的相对关系。 7 | 即新积木堆的高度Ti需要满足: 8 | 若Hi ≥ Hi+1,则Ti ≥ Ti+1 9 | 若Hi ≤ Hi+1,则Ti ≤ Ti+1 10 | 请问新积木堆的高度总和最小是多少? 11 | 12 | 关于输入 13 | 14 | 两行 15 | 第一行一个正整数,表示积木的个数n (n ≤ 1000000) 16 | 第二行包含n正整数,表示从左至右各积木的高度Hi (Hi ≤ 100000),相邻两数用空格隔开 17 | 18 | 关于输出 19 | 20 | 一个整数,表示经缩小后所需的最小积木高度之和 21 | 22 | 例子输入 23 | 24 | 5 25 | 1 10 2 7 7 26 | 27 | 例子输出 28 | 29 | 8 30 | 31 | 提示信息 32 | 33 | 样例[1 10 2 7 7]经过缩小后的结果为[1 2 1 2 2] 34 | *****/ 35 | 36 | #include 37 | #include 38 | using namespace std; 39 | 40 | /** 41 | 思路 42 | 43 | 首先,很容易想到,如果找到所有“谷”(谷的左右两侧都比谷大),那么就可以从谷向两侧扩展填充缩小后的高度。 44 | 而反过来想,任何一个位置的缩小后的高度要么是从该位置起向左的最长递减序列长度,要么是向右的(取二者较大值)。 45 | 那么问题就转化为求取每个位置的从左到右的最长递增序列长度和从右到左的最长递增序列长度。 46 | 用inc[i]记录以h[i]结尾的从左到右的最长递增序列长度,显然inc[0] = 1。 47 | 那么根据h[i]和h[i-1]的关系,有如下递推: 48 | 49 | 1. h[i] > h[i-1],那么递增序列长度加一,inc[i] = inc[i-1] + 1; 50 | 2. h[i] < h[i-1],那么递增序列长度为1,inc[i] = 1; 51 | 3. h[i] = h[i-1],那么递增序列长度不变,inc[i] = inc[i-1]。 52 | 53 | 反过来可以用相同的方法求取从右到左的递增序列长度数组dec。 54 | h[i]缩小后的高度就应该是max(inc[i], dec[i])。 55 | **/ 56 | 57 | #define MAX_N 1001000 58 | 59 | int h[MAX_N] = {0}, n = 0; 60 | int increase[MAX_N] = {0}, decrease[MAX_N] = {0}; 61 | 62 | void compute_increasing(int* inc, int* h) 63 | { 64 | inc[0] = 1; 65 | for (int i = 1; i < n; i++) 66 | if (h[i] > h[i - 1]) 67 | inc[i] = inc[i - 1] + 1; 68 | else if (h[i] < h[i - 1]) 69 | inc[i] = 1; 70 | else 71 | inc[i] = inc[i - 1]; 72 | } 73 | 74 | int main() 75 | { 76 | int ans = 0; 77 | cin >> n; 78 | for (int i = 0; i < n; i++) 79 | cin >> h[i]; 80 | compute_increasing(increase, h); 81 | reverse(h, h + n); 82 | compute_increasing(decrease, h); 83 | reverse(decrease, decrease + n); 84 | for (int i = 0; i < n; i++) 85 | ans += max(increase[i], decrease[i]); 86 | cout << ans << endl; 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /第四阶段编程练习2/缩小积木.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 考完计算概论B后,阿福开始浪的飞起.最近阿福发现一个有趣的游戏.在他的面前有n个积木,从左至右每 5 | 个积木的高度为Hi,其中Hi为正整数,1 ≤ i ≤ n, 现在他想要用高度较小的积木来重新搭建该图形, 6 | 同时还要保持原图形中相邻积木高度的相对关系。 7 | 即新积木堆的高度Ti需要满足: 8 | 若Hi ≥ Hi+1,则Ti ≥ Ti+1 9 | 若Hi ≤ Hi+1,则Ti ≤ Ti+1 10 | 请问新积木堆的高度总和最小是多少? 11 | 12 | 关于输入 13 | 14 | 两行 15 | 第一行一个正整数,表示积木的个数n (n ≤ 1000000) 16 | 第二行包含n正整数,表示从左至右各积木的高度Hi (Hi ≤ 100000),相邻两数用空格隔开 17 | 18 | 关于输出 19 | 20 | 一个整数,表示经缩小后所需的最小积木高度之和 21 | 22 | 例子输入 23 | 24 | 5 25 | 1 10 2 7 7 26 | 27 | 例子输出 28 | 29 | 8 30 | 31 | 提示信息 32 | 33 | 样例[1 10 2 7 7]经过缩小后的结果为[1 2 1 2 2] 34 | *****/ 35 | 36 | #include 37 | #include 38 | using namespace std; 39 | 40 | /** 41 | 思路 42 | 43 | 首先,很容易想到,如果找到所有“谷”(谷的左右两侧都比谷大),那么就可以从谷向两侧扩展填充缩小后的高度。 44 | 而反过来想,任何一个位置的缩小后的高度要么是从该位置起向左的最长递减序列长度,要么是向右的(取二者较大值)。 45 | 那么问题就转化为求取每个位置的从左到右的最长递增序列长度和从右到左的最长递增序列长度。 46 | 用inc[i]记录以h[i]结尾的从左到右的最长递增序列长度,显然inc[0] = 1。 47 | 那么根据h[i]和h[i-1]的关系,有如下递推: 48 | 49 | 1. h[i] > h[i-1],那么递增序列长度加一,inc[i] = inc[i-1] + 1; 50 | 2. h[i] < h[i-1],那么递增序列长度为1,inc[i] = 1; 51 | 3. h[i] = h[i-1],那么递增序列长度不变,inc[i] = inc[i-1]。 52 | 53 | 反过来可以用相同的方法求取从右到左的递增序列长度数组dec。 54 | h[i]缩小后的高度就应该是max(inc[i], dec[i])。 55 | **/ 56 | 57 | #define MAX_N 1001000 58 | 59 | int h[MAX_N] = {0}, n = 0; 60 | int increase[MAX_N] = {0}, decrease[MAX_N] = {0}; 61 | 62 | void compute_increasing(int* inc, int* h) 63 | { 64 | inc[0] = 1; 65 | for (int i = 1; i < n; i++) 66 | if (h[i] > h[i - 1]) 67 | inc[i] = inc[i - 1] + 1; 68 | else if (h[i] < h[i - 1]) 69 | inc[i] = 1; 70 | else 71 | inc[i] = inc[i - 1]; 72 | } 73 | 74 | int main() 75 | { 76 | int ans = 0; 77 | cin >> n; 78 | for (int i = 0; i < n; i++) 79 | cin >> h[i]; 80 | compute_increasing(increase, h); 81 | reverse(h, h + n); 82 | compute_increasing(decrease, h); 83 | reverse(decrease, decrease + n); 84 | for (int i = 0; i < n; i++) 85 | ans += max(increase[i], decrease[i]); 86 | cout << ans << endl; 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /综合练习/数组区域数目问题.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 有一个n*n的二维数组,里面存放的数字是0或者1。对于任何一个位置(i,j),我们定义 5 | (i-1,j),(i+1,j),(i,j-1),(i,j+1)为与其相邻的位置。所有相邻的位置,如果它 6 | 们中存放的数字都相同(都是0或者都是1),那么它们构成一个区域。现在请求出给定 7 | 的数组中有多少个区域。比如下面的数组中有3个区域,在框中的为一个区域,这个区域 8 | 左边和右边又分别有一个区域。 9 | +---+ 10 | 0 1 1 0 0|1 1|0 11 | | | 12 | 0 1 1 0 -----> 0|1 1|0 13 | +-+ | 14 | 0 0 1 0 0 0|1|0 15 | | +--+ 16 | 0 0 1 1 0 0| 1 1| 17 | +----+ 18 | 19 | 关于输入 20 | 21 | 第一行的数字表示有多少组输入。 22 | 每组测试样例分为两部分,一行只有一个数n(n<10),用来表示数组的维数,接下来n 23 | 行是数组中每一行的值。 24 | 25 | 关于输出 26 | 27 | 每行一个输出,表示数组中区域的个数。 28 | 29 | 例子输入 30 | 31 | 2 32 | 4 33 | 0 1 1 0 34 | 0 1 1 0 35 | 0 0 1 0 36 | 0 0 1 1 37 | 3 38 | 0 1 0 39 | 1 1 1 40 | 0 1 0 41 | 42 | 例子输出 43 | 44 | 3 45 | 5 46 | 47 | 提示信息 48 | 49 | 可以使用一个备用的数组visited[10][10],用来记录一个位置是否被访问过。 50 | 注意边界问题。 51 | *****/ 52 | 53 | #include 54 | #include 55 | using namespace std; 56 | 57 | #define MAX_N 20 58 | #define ND 4 59 | 60 | int arr[MAX_N][MAX_N] = {0}; 61 | int n = 0; 62 | const int dr[ND] = {1, -1, 0, 0}, dc[ND] = {0, 0, 1, -1}; 63 | 64 | void dfs(int r, int c, int val) 65 | { 66 | if (arr[r][c] != val) 67 | return; 68 | arr[r][c] = -1; 69 | for (int d = 0; d < ND; d++) 70 | dfs(r + dr[d], c + dc[d], val); 71 | } 72 | 73 | int main() 74 | { 75 | int ans = 0; 76 | cin >> n; 77 | while (cin >> n) 78 | { 79 | ans = 0; 80 | memset(arr, 0xff, sizeof(arr)); 81 | for (int i = 1; i <= n; i++) 82 | for (int j = 1; j <= n; j++) 83 | cin >> arr[i][j]; 84 | for (int i = 1; i <= n; i++) 85 | for (int j = 1; j <= n; j++) 86 | if (arr[i][j] >= 0) 87 | { 88 | dfs(i, j, arr[i][j]); 89 | ans++; 90 | } 91 | cout << ans << endl; 92 | } 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /第四阶段编程练习2/数组区域数目问题.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 有一个n*n的二维数组,里面存放的数字是0或者1。对于任何一个位置(i,j),我们定义 5 | (i-1,j),(i+1,j),(i,j-1),(i,j+1)为与其相邻的位置。所有相邻的位置,如果它 6 | 们中存放的数字都相同(都是0或者都是1),那么它们构成一个区域。现在请求出给定 7 | 的数组中有多少个区域。比如下面的数组中有3个区域,在框中的为一个区域,这个区域 8 | 左边和右边又分别有一个区域。 9 | +---+ 10 | 0 1 1 0 0|1 1|0 11 | | | 12 | 0 1 1 0 -----> 0|1 1|0 13 | +-+ | 14 | 0 0 1 0 0 0|1|0 15 | | +--+ 16 | 0 0 1 1 0 0| 1 1| 17 | +----+ 18 | 19 | 关于输入 20 | 21 | 第一行的数字表示有多少组输入。 22 | 每组测试样例分为两部分,一行只有一个数n(n<10),用来表示数组的维数,接下来n 23 | 行是数组中每一行的值。 24 | 25 | 关于输出 26 | 27 | 每行一个输出,表示数组中区域的个数。 28 | 29 | 例子输入 30 | 31 | 2 32 | 4 33 | 0 1 1 0 34 | 0 1 1 0 35 | 0 0 1 0 36 | 0 0 1 1 37 | 3 38 | 0 1 0 39 | 1 1 1 40 | 0 1 0 41 | 42 | 例子输出 43 | 44 | 3 45 | 5 46 | 47 | 提示信息 48 | 49 | 可以使用一个备用的数组visited[10][10],用来记录一个位置是否被访问过。 50 | 注意边界问题。 51 | *****/ 52 | 53 | #include 54 | #include 55 | using namespace std; 56 | 57 | #define MAX_N 20 58 | #define ND 4 59 | 60 | int arr[MAX_N][MAX_N] = {0}; 61 | int n = 0; 62 | const int dr[ND] = {1, -1, 0, 0}, dc[ND] = {0, 0, 1, -1}; 63 | 64 | void dfs(int r, int c, int val) 65 | { 66 | if (arr[r][c] != val) 67 | return; 68 | arr[r][c] = -1; 69 | for (int d = 0; d < ND; d++) 70 | dfs(r + dr[d], c + dc[d], val); 71 | } 72 | 73 | int main() 74 | { 75 | int ans = 0; 76 | cin >> n; 77 | while (cin >> n) 78 | { 79 | ans = 0; 80 | memset(arr, 0xff, sizeof(arr)); 81 | for (int i = 1; i <= n; i++) 82 | for (int j = 1; j <= n; j++) 83 | cin >> arr[i][j]; 84 | for (int i = 1; i <= n; i++) 85 | for (int j = 1; j <= n; j++) 86 | if (arr[i][j] >= 0) 87 | { 88 | dfs(i, j, arr[i][j]); 89 | ans++; 90 | } 91 | cout << ans << endl; 92 | } 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /综合练习/连续邮资问题.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 假设某国际发行了n种不同面值的邮票,并且规定每张信封上最多只允许贴m张邮票。连续邮资问 5 | 题要求对于给定的n和m的值,给出邮票面值的最佳设计,使得可在一张信封上贴出从邮资1开始, 6 | 增量为1的最大连续邮资区间。例如当n=5和m=4时,面值为(1,3,11,15,32)的5种邮票可 7 | 以贴出邮资的最大连续邮资区间是1到70。 8 | 9 | 关于输入 10 | 11 | 输入数据每一行给出2个正整数n和m的值(1<=n,m<=9),最后以0 0 表示文件结束。 12 | 13 | 关于输出 14 | 15 | 对于输入中每一行的正整数n和m,将最大连续邮资区间输出。 16 | 17 | 例子输入 18 | 19 | 5 4 20 | 0 0 21 | 22 | 例子输出 23 | 24 | 70 25 | *****/ 26 | 27 | #include 28 | #include 29 | #include 30 | using namespace std; 31 | 32 | #define MAX_N 10 33 | #define MAX_VAL 1000 34 | 35 | int val[MAX_N] = {1}; 36 | int q[MAX_VAL] = {0}; 37 | int h[MAX_VAL] = {0}; 38 | int n = 0, m = 0; 39 | int ans = 0; 40 | 41 | int bfs() 42 | { 43 | /** Init **/ 44 | int tail = 0, head = 0; 45 | memset(h, 0x00, sizeof(h)); 46 | q[head++] = 0; 47 | /** BFS **/ 48 | for (int s = 0; head > tail && s < m; s++) 49 | { 50 | int _head = head; 51 | while (_head > tail) 52 | { 53 | for (int j = 0; j < n; j++) 54 | { 55 | if (!val[j]) 56 | break; 57 | int tmp = q[tail] + val[j]; 58 | if (!h[tmp]) 59 | { 60 | h[tmp] = 1; 61 | q[head++] = tmp; 62 | } 63 | } 64 | tail++; 65 | } 66 | } 67 | /** Find max **/ 68 | int ret = 1; 69 | while (h[++ret]); 70 | return ret - 1; 71 | } 72 | 73 | void dfs(int depth, int cur_max) 74 | { 75 | if (depth >= n) 76 | { 77 | ans = max(ans, cur_max); 78 | return; 79 | } 80 | for (int v = val[depth - 1] + 1; v <= cur_max + 1; v++) 81 | { 82 | val[depth] = v; 83 | dfs(depth + 1, bfs()); 84 | val[depth] = 0; 85 | } 86 | } 87 | 88 | int main() 89 | { 90 | while(cin >> n >> m) 91 | { 92 | if (!n && !m) 93 | return 0; 94 | dfs(1, m); 95 | cout << ans << endl; 96 | } 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /2021年期末考试题/最小外包矩形.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 最小外包矩形是图形学中一个重要的概念,其定义是能够包围几何对象(可以视为一组点的集合), 5 | 且平行于x,y轴的最小外接矩形。 6 | 想要生成最小外包矩形,只需要统计组成该几何对象所有点的x、y坐标的最大值和最小值即可。 7 | 最小外包矩形左下角的点x坐标等于所有点的x坐标的最小值,y坐标等于所有点的y坐标的最小值, 8 | 同样的,右上角的点x坐标等于所有点的x坐标的最大值,y坐标等于所有点的y坐标的最大值。 9 | 特别地,如果几何对象为一个点,最小外包矩形变成一个点,可以用4个位置一样的点表示,如果为 10 | 水平/垂直线段,最小外包矩形变成一条线段,用两对相等的点表示。 11 | 请你根据输入的点的信息输出最小外包矩形的信息。 12 | 13 | 关于输入 14 | 15 | 第一行为整数,表示所有的点个数。 16 | 每一行包含3个整数,从左到右分别是点所属于的几何对象的ID、点的x坐标、点的y坐标。 17 | 18 | 关于输出 19 | 20 | 输出的结果每行按照几何体的ID从小到大排序,每一行有5个,从左到右依次是: 21 | 几何体ID、左下角点x坐标,左下角点y坐标、右上角点x坐标、右上角点y坐标。 22 | 23 | 例子输入 24 | 25 | 10 26 | 2 36 191 27 | 3 289 107 28 | 1 943 265 29 | 4 447 806 30 | 1 730 371 31 | 1 7 102 32 | 4 549 630 33 | 4 85 955 34 | 2 841 967 35 | 2 932 309 36 | 37 | 例子输出 38 | 39 | 1 7 102 943 371 40 | 2 36 191 932 967 41 | 3 289 107 289 107 42 | 4 85 630 549 955 43 | 44 | 提示信息 45 | 46 | 几何体的ID并不是按照顺序输入的。 47 | *****/ 48 | 49 | #include 50 | #include 51 | using namespace std; 52 | 53 | #define MAX_N 10000 54 | #define MAX_INT 0x7fffffff 55 | #define MIN_INT 0x80000000 56 | 57 | struct Rectangle 58 | { 59 | int row_min, row_max; 60 | int col_min, col_max; 61 | } rect[MAX_N] = {{0, 0, 0, 0}}; 62 | 63 | void init() 64 | { 65 | for (int i = 0; i < MAX_N; i++) 66 | { 67 | rect[i].row_min = rect[i].col_min = MAX_INT; 68 | rect[i].row_max = rect[i].col_max = MIN_INT; 69 | } 70 | } 71 | 72 | int main() 73 | { 74 | int n = 0; 75 | int r = 0, c = 0, id = 0; 76 | init(); 77 | cin >> n; 78 | while (n--) 79 | { 80 | cin >> id >> r >> c; 81 | rect[id].row_min = min(rect[id].row_min, r); 82 | rect[id].col_min = min(rect[id].col_min, c); 83 | rect[id].row_max = max(rect[id].row_max, r); 84 | rect[id].col_max = max(rect[id].col_max, c); 85 | } 86 | for (int i = 0; i < MAX_N; i++) 87 | if (rect[i].row_min != MAX_INT) 88 | cout << i << " " << rect[i].row_min << " " << rect[i].col_min << " " << rect[i].row_max << " " << rect[i].col_max << endl; 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /综合练习/代码查重.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 五道口某职业学校开设了一门名为计算概论的课程。这门课程开设最初,老师、同学、助教相亲相爱,十分和谐。 5 | 直到有一天,一名丧心病狂的助教写了一个代码查重程序,之前的温馨和谐的关系开始崩坏。学生们甚至发生了暴 6 | 动,这个事件被后世成为T大计算机系灭门惨案。 7 | 十年过去了,为了研究T大计算机系灭门惨案的始末,P大的老师让同学们实现那名丧心病狂的助教写的伤害了无数 8 | 无辜同学的查重程序的简化版本。 9 | 输入两份代码,分别统计两份代码中的if,switch,while,for语句的数量,若两份代码中if和switch的数量之 10 | 和,与while、for之和分别都相等,则判定这两份代码有相互抄袭的嫌疑。【简直丧心病狂! 11 | 12 | 关于输入 13 | 14 | 第1行一个整数n,代表第一份代码的行数 15 | 随后从2到n+1行为第一份代码 16 | 第n+2行一个整数m,代表第二份代码的行数 17 | 随后从n+3到n+m+2行为第二份代码 18 | 19 | 关于输出 20 | 21 | 一行, 两份代码有相互抄袭的嫌疑, 输出Yes,否则输出No 22 | 23 | 例子输入 24 | 25 | 3 26 | int main() { 27 | printf("Hello World!"); 28 | } 29 | 4 30 | int main() 31 | { 32 | printf("Hello World!"); 33 | } 34 | 35 | 例子输出 36 | 37 | Yes 38 | 39 | 提示信息 40 | 41 | We’ll be using a sophisticated cheat checker that compares handins between all students. 42 | Please don’t copy another student’s code. 43 | *****/ 44 | 45 | #include 46 | #include 47 | using namespace std; 48 | 49 | void strip(char *s) 50 | { 51 | int l = strlen(s); 52 | int idx = 0; 53 | for (int i = 0; i <= l; ++i) 54 | if (s[i] != ' ') 55 | s[idx++] = s[i]; 56 | } 57 | 58 | void CNT(char *s, int &cnt1, int &cnt2) 59 | { 60 | strip(s); 61 | int l = strlen(s); 62 | const char word[4][10] = { "if", "switch", "while", "for" }; 63 | for (int i = 0; i < l; ++i) { 64 | for (int j = 0; j < 4; ++j) { 65 | char saved = s[i + strlen(word[j])]; 66 | s[i + strlen(word[j])] = '\0'; 67 | if (strcmp(word[j], s + i) == 0 && saved == '(') { 68 | if (i < 2) 69 | cnt1 += 1; 70 | else 71 | cnt2 += 1; 72 | } 73 | s[i + strlen(word[j])] = saved; 74 | } 75 | } 76 | } 77 | 78 | int main() 79 | { 80 | char s[1010]; 81 | int n1, n2, cnt11 = 0, cnt12 = 0, cnt21 = 0, cnt22 = 0; 82 | cin >> n1; 83 | cin.get(); 84 | while (n1--) { 85 | cin.getline(s, 1000); 86 | CNT(s, cnt11, cnt12); 87 | } 88 | cin >> n2; 89 | cin.get(); 90 | while (n2--) { 91 | cin.getline(s, 1000); 92 | CNT(s, cnt21, cnt22); 93 | } 94 | bool res = cnt11 == cnt21 && cnt12 == cnt22; 95 | cout << (res ? "Yes" : "No") << endl; 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /第四阶段编程练习2/求最长回文子串.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 给定一个串S,长度小于等于100000,求S的最长回文子串的长度(回文串是指一个串正序和逆序相同)。 5 | 6 | 关于输入 7 | 8 | 给定的字符串S 9 | 10 | 关于输出 11 | 12 | 一个数,表示最长回文子串的长度 13 | 14 | 例子输入 15 | 16 | aaabbac 17 | 18 | 例子输出 19 | 20 | 4 21 | 22 | 提示信息 23 | 24 | 暴力会超时,用分治吧 25 | *****/ 26 | 27 | #include 28 | #include 29 | #include 30 | using namespace std; 31 | 32 | #define MAX_N 1001000 33 | 34 | const int P = 131; 35 | char str[MAX_N]; 36 | unsigned long long h1[MAX_N], h2[MAX_N], p[MAX_N]; 37 | 38 | /** 正向哈希 **/ 39 | unsigned long long hash1(int l, int r) 40 | { 41 | return h1[r] - h1[l - 1] * p[r - l + 1]; 42 | } 43 | 44 | /** 反向哈希 **/ 45 | unsigned long long hash2(int l, int r) 46 | { 47 | return h2[l] - h2[r + 1] * p[r - l + 1]; 48 | } 49 | 50 | int main() 51 | { 52 | cin >> str + 1; 53 | int len = strlen(str + 1); 54 | 55 | /** 构造哈希 **/ 56 | h1[0] = 0; 57 | for(int i = 1; i <= len; i++) 58 | h1[i] = h1[i - 1] * P + (str[i] - 'a' + 1); 59 | h2[len + 1] = 0; 60 | for(int i = len; i >= 1; i--) 61 | h2[i] = h2[i + 1] * P + (str[i] - 'a' + 1); 62 | p[0] = 1; 63 | for(int i = 1;i < MAX_N; i++) 64 | p[i] = p[i - 1] * P; 65 | 66 | int ans = 0; 67 | /** 枚举各个位置,以其为中心扩展出回文串 **/ 68 | for(int i = 1; i <= len; i++) 69 | { 70 | /** 奇数长度回文 **/ 71 | int l = 0, r = min(i - 1, len - i); 72 | while(l < r) // 二分查找最长回文串 73 | { 74 | int mid = (l + r + 1) / 2; 75 | if(hash1(i - mid, i - 1) == hash2(i + 1, i + mid)) 76 | l = mid; 77 | else 78 | r = mid - 1; 79 | } 80 | ans=max(ans, l + l + 1); 81 | 82 | /** 偶数长度回文 **/ 83 | l = 0; 84 | r = min(i - 1, len - i + 1); 85 | while(l < r) // 二分查找 86 | { 87 | int mid = (l + r + 1) / 2; 88 | if(hash1(i - mid, i - 1) == hash2(i, i + mid - 1)) 89 | l = mid; 90 | else r = mid - 1; 91 | } 92 | ans = max(ans, l + l); 93 | } 94 | cout << ans << endl; 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /第三阶段编程练习4/平衡矩阵.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 现在有一个n阶正整数方阵(n<=7),现在可以对矩阵的任意一行进行左移,具体操作为:每次对于 5 | 某一行a_i1,a_i2,…,a_in进行一次左移,最左边的元素移动到这一行的末尾,其他元素均向左移动 6 | 一位,即变为a_i2,a_i3,…,a_in,a_i1。对某一行可以执行任意次的左移。 7 | 现在我们的目标是:通过对矩阵的每一行进行若干次左移,使得矩阵中每列和的最大值最小。 8 | 9 | 关于输入 10 | 11 | 输入包含多组数据。 12 | 对于每组数据,第一行为一个正整数n(1<=n<=7),代表矩阵的阶。接下来的n行,每行n个正整数 13 | (不超过10000),代表这个矩阵。 14 | 输入数据以一个-1为结尾代表输入结束。 15 | 16 | 关于输出 17 | 18 | 对于每组数据,输出一行一个正整数,为最小的最大列和。 19 | 20 | 例子输入 21 | 22 | 2 23 | 4 6 24 | 3 7 25 | 3 26 | 1 2 3 27 | 4 5 6 28 | 7 8 9 29 | -1 30 | 31 | 例子输出 32 | 33 | 11 34 | 15 35 | *****/ 36 | 37 | #include 38 | #include 39 | #include 40 | using namespace std; 41 | 42 | #define MAX_N 10 43 | #define MAX_INT 0x7fffffff 44 | 45 | int arr[MAX_N][MAX_N] = {0}, n = 0; // 矩阵 46 | int sum[MAX_N] = {0}; // 各列之和 47 | 48 | /** 左移arr中的row那一行,并更新sum **/ 49 | void shift_left(int row) 50 | { 51 | for (int j = 0; j < n; j++) 52 | sum[j] -= arr[row][j]; 53 | reverse(arr[row], arr[row] + n); // arr[0],arr[1],...,arr[n-1] => arr[n-1],arr[n-2],...,arr[0] 54 | reverse(arr[row], arr[row] + n - 1); // arr[n-1],arr[n-2],...,arr[0] => arr[1],arr[2],...,arr[n-1],arr[0] 55 | for (int j = 0; j < n; j++) 56 | sum[j] += arr[row][j]; 57 | } 58 | 59 | /** 深度优先搜索 **/ 60 | int dfs(int depth) 61 | { 62 | if (depth >= n) 63 | return *max_element(sum, sum + n); // max_element返回sum到sum+n中(左闭右开)最大的元素的地址 64 | int ret = dfs(depth + 1); // 本行不左移,直接向下递归 65 | for (int i = 1; i < n; i++) 66 | { 67 | shift_left(depth); // 本行左移 68 | ret = min(ret, dfs(depth + 1)); // 向下递归,保留最小值 69 | } 70 | return ret; 71 | } 72 | 73 | int main() 74 | { 75 | while(cin >> n) 76 | { 77 | if (n < 0) 78 | return 0; 79 | memset(sum, 0x00, sizeof(sum)); 80 | for (int i = 0; i < n; i++) 81 | for (int j = 0; j < n; j++) 82 | { 83 | cin >> arr[i][j]; 84 | sum[j] += arr[i][j]; 85 | } 86 | cout << dfs(0) << endl; 87 | } 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /第三阶段编程练习5/合唱队形.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学不交换位置就能排成合唱队形。 5 | 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1, 2, …, K,他们的身高分别为T1, T2, …, 6 | TK,则他们的身高满足T1 < T2 < … < Ti , Ti > Ti+1 > … > TK (1 <= i <= K)。 7 | 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。 8 | 9 | 关于输入 10 | 11 | 输入的第一行是一个整数N(2 <= N <= 100),表示同学的总数。第一行有n个整数,用空格分隔,第i个整数 12 | Ti(130 <= Ti <= 230)是第i位同学的身高(厘米)。 13 | 14 | 关于输出 15 | 16 | 输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。 17 | 18 | 例子输入 19 | 20 | 8 21 | 186 186 150 200 160 130 197 220 22 | 23 | 例子输出 24 | 25 | 4 26 | *****/ 27 | 28 | #include 29 | #include 30 | using namespace std; 31 | 32 | #define MAX_N 200 33 | 34 | /** 35 | 思路:两次动态规划 36 | 37 | 首先介绍最长上升子序列问题。 38 | 在有n个元素的数组nums中,若有0 <= i1 < i2 < ... < it < n,且nums[i1] < nums[i2] < ... < nums[it], 39 | 则nums[i1], nums[i2], ..., nums[it]是nums的一个上升子序列。问题是如何求取nums的最长上升子序列的长度。 40 | 41 | 用dp[i]来表示以nums[i]为结束的上升子序列的最长长度。 42 | 显然只要有j < i且nums[j] < nums[i],那么就可以用在nums[j]结尾的最长子序列后面拼上nums[i],得到长度为dp[j] + 1的上升子序列。 43 | 而如果不存在这样的j,说明nums[i]是目前为止最小的数,其单独也可以作为一个上升子序列,长度为1。 44 | 因此dp[i] = max(1, dp[j] + 1), if 0 <= j < i and nums[j] < nums[i] 45 | 当计算完dp数组后,遍历找到最大的dp[i]即得到了最长上升子序列的长度。 46 | 47 | 下面来考虑本题目,题目要求找到最长的先升再降的子序列。因此我们可以先计算上升子序列dp1,再倒过来计算上升子序列dp2。 48 | dp1[i]表示以nums[i]为结束的上升子序列的最长长度,dp2[i]表示将从尾到头看nums数组,以nums[i]为结束的上升子序列的最长长度。 49 | 那么dp1[i] + dp2[i] - 1就是以nums[i]为拐点的先升再降子序列的最长长度。遍历所有位置找到最大即可。 50 | **/ 51 | 52 | int main() 53 | { 54 | int dp1[MAX_N] = {0}, dp2[MAX_N] = {0}; 55 | int h[MAX_N] = {0}, n = 0, ans = -1; 56 | cin >> n; 57 | for (int i = 0; i < n; i++) 58 | cin >> h[i]; 59 | for (int i = 0; i < n; i++) 60 | { 61 | dp1[i] = 1; 62 | for (int j = 0; j < i; j++) 63 | if (h[j] < h[i]) 64 | dp1[i] = max(dp1[i], dp1[j] + 1); 65 | } 66 | for (int i = n - 1; i >= 0; i--) 67 | { 68 | dp2[i] = 1; 69 | for (int j = n - 1; j > i; j--) 70 | if (h[j] < h[i]) 71 | dp2[i] = max(dp2[i], dp2[j] + 1); 72 | } 73 | for (int i = 0; i < n; i++) 74 | ans = max(ans, dp1[i] + dp2[i] - 1); 75 | cout << n - ans << endl; 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /2021年期末考试题/任意K进制长纯小数加法运算.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 任意输入两个K进制纯小数,均为正数,计算其和,其中,1 < K < 11。所谓纯小数是指整数部分为0, 5 | 一定有小数位(允许小数位都为0)。假定小数部分的长度不超过100位。 6 | 7 | 关于输入 8 | 9 | 第1行,是小数对的个数 n; 10 | 之后是 n 行,每行格式是: 11 | k m1 m2 12 | 其中,k表示后面的 m1 和 m2 是k进制,m1和m2为k进制纯小数。中间均按空格间隔。 13 | 注意:输入的纯小数末位可能会带有0 14 | 15 | 关于输出 16 | 17 | 输出为对应的 n 行相加的结果。 18 | 规定:结果值的小数位末位不能是0,如果小数位都为0,也必须有小数点。 19 | 20 | 例子输入 21 | 22 | 4 23 | 2 0.1000110111 0.000011111111101 24 | 3 0.1210000001 0.210000010001211 25 | 2 0.1011 0.00110 26 | 10 0.499 0.501 27 | 28 | 例子输出 29 | 30 | 0.100111011011101 31 | 1.101000010101211 32 | 0.111 33 | 1. 34 | *****/ 35 | 36 | #include 37 | #include 38 | #include 39 | using namespace std; 40 | 41 | #define MAX_LEN 110 42 | 43 | int base = 0, c = 0; 44 | 45 | void zero_pad(char *a, char *b) 46 | { 47 | for (int i = strlen(b); a[i] != '\0'; i++) 48 | b[i] = '0'; 49 | } 50 | 51 | int add(int base, char *a, char *b) 52 | { 53 | int c = 0; 54 | reverse(a, a + strlen(a)); 55 | reverse(b, b + strlen(b)); 56 | for (int i = 0; a[i] != '\0'; i++) 57 | { 58 | a[i] = a[i] - '0' + b[i] - '0' + c; 59 | c = a[i] / base; 60 | a[i] = a[i] % base + '0'; 61 | } 62 | reverse(a, a + strlen(a)); 63 | return c; 64 | } 65 | 66 | void remove_zero_pad(char *a) 67 | { 68 | for (int i = strlen(a) - 1; i >= 0 && a[i] == '0'; i--) 69 | a[i] = '\0'; 70 | } 71 | 72 | int main() 73 | { 74 | char *a = new char[MAX_LEN], *b = new char[MAX_LEN], tmp_c = '\0'; 75 | int base = 0, n = 0, tmp = 0; 76 | cin >> n; 77 | while (n--) 78 | { 79 | memset(a, 0x00, sizeof(char) * MAX_LEN); 80 | memset(b, 0x00, sizeof(char) * MAX_LEN); 81 | cin >> base; 82 | cin >> tmp >> tmp_c >> a; 83 | cin >> tmp >> tmp_c >> b; 84 | if (strlen(a) < strlen(b)) // Swap if a is shorter than b 85 | { 86 | char *t = a; 87 | a = b; 88 | b = t; 89 | } 90 | zero_pad(a, b); 91 | tmp = add(base, a, b); 92 | remove_zero_pad(a); 93 | cout << tmp << "." << a << endl; 94 | } 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /期末考试/合理的饭票设计.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 以前大学食堂都使用餐票吃饭,每顿饭菜钱可以为1角,2角,...,最多为n角。如果规定每次吃 5 | 饭最多只能使用k张餐票,是否可以设计m种不同面值的餐票,使得餐票从1开始可以连续覆盖的面 6 | 值范围恰好为 1 - n(角)?满足上述条件的方案有多少? 7 | 假设 n 的值不超过500,饭菜钱单位为角。 8 | 例如, 9 | m=3, k=2, n=8, 则,面值为:{1,3,4} 恰好覆盖 1,2,...,8,此时,1角只需要1张面值为1的 10 | 即可,2角需要2张面值为1的,3角只需要1张面值为3的,4角只需要1张面值为4的,5角需要1张 11 | 面值为1的再加上1张面值为4的,6角需要2张面值为3的,7角需要1张面值为3再加上1张面值为4 12 | 的,8角需要2张面值为4的。即:只需要2张面值的饭票即可覆盖1-8的范围(注意:一定是连续 13 | 覆盖)。除了这三种面值之外,再没有其他方案的面值。因此,这样的方案有1种。 14 | 若m=3, k=2, n=9, 则不存在面值组合,因此,为0种方案。 15 | 若m=3, k=2, n=6,则有 {1,2,3},{1,2,4}和{1,3,5}共3种。 16 | 若m=3, k=2, n=5, 则不存在,因此,为0种。 17 | 18 | 关于输入 19 | 20 | 第1行输入正整数 P, 表示后面有 P行 21 | 后面的P行分别为 m,k,n,其间以空格间隔 22 | 23 | 关于输出 24 | 25 | 对应输出 P行,若不存在 m 种面值的饭票,则输出0,若有,则输出方案数。 26 | 27 | 例子输入 28 | 29 | 4 30 | 3 2 5 31 | 3 2 6 32 | 3 2 8 33 | 3 2 9 34 | 35 | 例子输出 36 | 37 | 0 38 | 3 39 | 1 40 | 0 41 | 42 | 提示信息 43 | 44 | 注意代码运行效率,可以注意对一些重复操作进行优化。 45 | *****/ 46 | 47 | #include 48 | using namespace std; 49 | 50 | #define MAX_N 1000 51 | 52 | int ac[MAX_N] = {0}, p[MAX_N] = {0}; 53 | int n = 0, m = 0, k = 0, ans = 0; 54 | 55 | void dfs(int x,int mx) 56 | { 57 | if(mx < 0) 58 | return; 59 | if(x > m) 60 | { 61 | if(mx == n) 62 | ans++; 63 | return; 64 | } 65 | int *tmp = new int[MAX_N]; 66 | for(int i = p[x - 1] + 1;i <= mx + 1; i++) 67 | { 68 | p[x] = i; 69 | int r = min(i * k, n + 1), j = 0; 70 | for(j = i; j <= r; j++) 71 | { 72 | tmp[j] = ac[j]; 73 | ac[j] = min(ac[j], ac[j - i] + 1); 74 | } 75 | if(ac[n + 1] > k) 76 | { 77 | for(j = i; j <= r + 1; j++) 78 | if(ac[j] > k) 79 | { 80 | dfs(x + 1, j - 1); 81 | break; 82 | } 83 | } 84 | for(j = i; j <= r; j++) 85 | ac[j] = tmp[j]; 86 | } 87 | } 88 | 89 | int main() 90 | { 91 | int t = 0; 92 | cin >> t; 93 | while(t--) 94 | { 95 | cin >> m >> k >> n; 96 | ans = 0; 97 | for(int i = 1; i <= n + 1; i++) 98 | ac[i] = n + n; 99 | for(int i = 0; i <= k; i++) 100 | ac[i]=i; 101 | p[1] = 1; 102 | dfs(2, k); 103 | cout << ans << endl; 104 | } 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /期末考试/四则运算表达式的值.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 输入一个包括+、-、*、/和()的四则运算表达式,你能算出表达式的值吗? 5 | 这个表达式满足: 6 | 1、没有括号不匹配的情况,但可能有嵌套的情形 7 | 2、操作数均为整数,但需考虑正负数 8 | 3、没有非法表达式,也没有零作除数的情况 9 | 4、所有操作都可以视为整型计算,不考虑分数和小数的情况 10 | 5、中间结果和最终结果不会超出int的表示范围 11 | 12 | 关于输入 13 | 14 | 若干行,每行为一个合法的四则运算表达式 15 | 16 | 关于输出 17 | 18 | 若干行,为对应的运算结果 19 | 20 | 例子输入 21 | 22 | 1+3+5 23 | 5*(3+7) 24 | -(-4/(1+3))*5-1*2*3 25 | +2+3+5 26 | 27 | 例子输出 28 | 29 | 9 30 | 50 31 | -1 32 | 10 33 | 34 | 提示信息 35 | *****/ 36 | 37 | #include 38 | #include 39 | #include 40 | using namespace std; 41 | 42 | #define MAX_LEN 100000 43 | 44 | char a[MAX_LEN] = "\0"; 45 | 46 | /** Bracket match **/ 47 | int match_bracket(int l, int r) 48 | { 49 | int cnt = 1, ans = 0; 50 | for (int i = r - 1; i >= l; i--) { 51 | if (a[i] == ')') 52 | cnt++; 53 | else if (a[i] == '(') 54 | cnt--; 55 | if (cnt == 0) { 56 | ans = i; 57 | break; 58 | } 59 | } 60 | return ans; 61 | } 62 | 63 | int compute(int l, int r) 64 | { 65 | /** Low priority (addition, subtraction) **/ 66 | for (int i = r; i >= l; i--) 67 | { 68 | if (a[i] == ')') 69 | i = match_bracket(l, i); 70 | if (a[i] == '+') 71 | return compute(i + 1, r) + compute(l, i - 1); 72 | if (a[i] == '-') 73 | return compute(l, i - 1) - compute(i + 1, r); 74 | } 75 | /** Medium priority (multiplication, division) **/ 76 | for (int i = r; i >= l; i--) 77 | { 78 | if (a[i] == ')') 79 | i = match_bracket(l, i); 80 | if (a[i] == '*') 81 | return compute(i + 1, r) * compute(l, i - 1); 82 | if (a[i] == '/') 83 | return compute(l, i - 1) / compute(i + 1, r); 84 | } 85 | /** High priority (bracket) **/ 86 | if (a[r] == ')') 87 | return compute(l + 1, r - 1); 88 | /** Number only **/ 89 | if (a[r] >= '0' && a[r] <= '9') 90 | { 91 | int ans = 0, j = 0; 92 | for (int i = r; i >= l; i--, j++) 93 | ans += pow(10.0, (double)j) * (a[i] - '0'); 94 | return ans; 95 | } 96 | return 0; 97 | } 98 | 99 | int main() 100 | { 101 | while (cin.getline(a, MAX_LEN)) 102 | cout << compute(0, strlen(a) - 1) << endl; 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /第四阶段编程练习1/马和电话.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 小明在家十分无聊,他发现他手边有如下所示的电话拨号盘 5 | | 1 | 2 | 3 | 6 | | 4 | 5 | 6 | 7 | | 7 | 8 | 9 | 8 | | 0 | 9 | 和一个象棋棋子“马” 10 | 他先将“马”放在电话拨号盘的任意键上,接下来,棋子将会按照“马走日”的方式跳 N-1 步。 11 | 每一步必须是从一个数字键跳到另一个数字键,例如可以从1跳到8或6,而从5不能跳到其他任何 12 | 地方。 13 | 每当它落在一个键上(包括初始位置),都会拨出键所对应的数字,总共按下 N 位数字。 14 | 请问小明能用这种方式拨出多少个不同的号码? 15 | 16 | 关于输入 17 | 18 | 输入一个整数N,表示马跳的步数。 19 | 20 | 关于输出 21 | 22 | 输出小明能拨出的号码总数 23 | 24 | 例子输入 25 | 26 | 2 27 | 28 | 例子输出 29 | 30 | 20 31 | 32 | 提示信息 33 | 34 | N=1时,第一步棋子可落在{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}一共10个位置上。 35 | N=2时,第一步棋子可落在{1, 2, 3, 4, 6, 7, 8, 9, 0}一共9个位置上。 36 | 第二步,从1出发的棋子可落在6或8,拨出16或18; 37 | 从2出发的棋子可落在7或9,拨出27或29; 38 | 从3出发的棋子可落在4或8,拨出34或38; 39 | 从4出发的棋子可落在3或9或0,拨出43或49或40; 40 | 从6出发的棋子可落在1或7或0,拨出61或67或60; 41 | 从7出发的棋子可落在2或6,拨出72或76; 42 | 从8出发的棋子可落在1或3,拨出81或83; 43 | 从9出发的棋子可落在2或4,拨出92或94; 44 | 从0出发的棋子可落在4或6,拨出04或06。一共是20种拨号方式。 45 | 46 | 由与5不能跳到其他任何位置,其他任何位置也不能跳到5,当N>1时,初始位置不会选择5。 47 | 我们输入保证2<=N<=20 48 | *****/ 49 | 50 | #include 51 | using namespace std; 52 | 53 | #define N_DIGIT 10 54 | #define MAX_N 30 55 | 56 | /** 57 | 思路 -- 动态规划 58 | 59 | 假设有二维数组dp,dp[i][j]表示共i步且马的起始位置在j时共有几种跳法。 60 | 显然,dp[1][j] = 1,因为马不需要跳,直接放到拨号盘上的j位置即可。 61 | 假设对任意的j,dp[i-1][j]都已经求解完成,考虑如何计算dp[i][j]。 62 | 从j位置出发跳一步后到j'位置,之后共有dp[i-1][j']种跳法,那么考虑所有j'即可: 63 | dp[i][j] = sum_j'(dp[i-1][j']), where j' is a legal jump from j 64 | **/ 65 | 66 | int jump[N_DIGIT][N_DIGIT] = 67 | { 68 | {4, 6, -1}, // 0 69 | {6, 8, -1}, // 1 70 | {7, 9, -1}, // 2 71 | {4, 8, -1}, // 3 72 | {0, 3, 9, -1}, // 4 73 | {-1}, // 5 74 | {0, 1, 7, -1}, // 6 75 | {2, 6, -1}, // 7 76 | {1, 3, -1}, // 8 77 | {2, 4, -1}, // 9 78 | }; 79 | int dp[MAX_N][N_DIGIT] = {0}; 80 | 81 | int main() 82 | { 83 | int n = 0, ans = 0; 84 | cin >> n; 85 | for (int i = 0; i < N_DIGIT; i++) 86 | dp[1][i] = 1; 87 | for (int i = 2; i <= n; i++) 88 | for (int j = 0; j < N_DIGIT; j++) 89 | for (int k = 0; jump[j][k] >= 0; k++) 90 | dp[i][j] += dp[i - 1][jump[j][k]]; 91 | for (int i = 0; i < N_DIGIT; i++) 92 | ans += dp[n][i]; 93 | cout << ans << endl; 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /综合练习/矩阵乘方和.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 给出一个n*n的矩阵A和正整数k,请求出S=A+A^2+A^3+A^4+...+A^k的值.mat^x表示x个A相乘的结果. 5 | 6 | 关于输入 7 | 8 | 输入包含一组数据. 9 | 第一行是三个正整数n k m, (n<=30,k<=1000000000,m<=10000). 10 | 接下来n行,每行n个数,表示这个矩阵. 11 | 12 | 关于输出 13 | 14 | 输出矩阵S对m取模后的值(即:每个元素对 m 取余),包括n行,每行n个数 15 | 16 | 例子输入 17 | 18 | 2 2 4 19 | 0 1 20 | 1 1 21 | 22 | 例子输出 23 | 24 | 1 2 25 | 2 3 26 | *****/ 27 | 28 | #include 29 | #include 30 | using namespace std; 31 | 32 | #define MAX_N 40 33 | 34 | struct Matrix 35 | { 36 | int mat[MAX_N * 2][MAX_N * 2]; 37 | }; 38 | int n = 0, k = 0, m = 0; 39 | 40 | Matrix mul(Matrix &a, Matrix &b) 41 | { 42 | Matrix ret; 43 | for(int i = 1;i <= n; i++) 44 | for(int j = 1;j <= n; j++) 45 | { 46 | ret.mat[i][j]=0; 47 | for(int k = 1; k <= n; k++) 48 | { 49 | ret.mat[i][j] += (a.mat[i][k] * b.mat[k][j]) % m; 50 | ret.mat[i][j] %= m; 51 | } 52 | } 53 | return ret; 54 | } 55 | 56 | Matrix exp(Matrix &a, int x) 57 | { 58 | Matrix ret; 59 | for(int i = 1; i <= n; i++) 60 | for(int j = 1; j <= n; j++) 61 | ret.mat[i][j] = (i == j ? 1 : 0); 62 | for(; x ; x >>= 1) 63 | { 64 | if(x & 1) 65 | ret = mul(ret, a); 66 | a = mul(a, a); 67 | } 68 | return ret; 69 | } 70 | 71 | int main() 72 | { 73 | Matrix a, b; 74 | memset(a.mat, 0, sizeof(a.mat)); 75 | memset(b.mat, 0, sizeof(b.mat)); 76 | cin >> n >> k >> m; 77 | 78 | for(int i = 1; i <= n; i++) 79 | for(int j = 1; j <= n; j++) 80 | { 81 | cin >> a.mat[i][j + n]; 82 | b.mat[i + n][j + n] = a.mat[i][j + n]; 83 | } 84 | for(int i = 1;i <= n; i++) 85 | { 86 | b.mat[i][i] = 1; 87 | b.mat[i+n][i] = 1; 88 | } 89 | n = n * 2; 90 | 91 | b = exp(b, k); 92 | a = mul(a, b); 93 | for(int i = 1;i + i <= n; i++) 94 | { 95 | for(int j = 1;j + j <= n; j++) 96 | cout << a.mat[i][j] << " "; 97 | cout << endl; 98 | } 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /综合练习/循环数.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 当一个N位的整数X满足下列条件时,称其为循环数:X与任意一个整数1≤Y ≤ N相乘时,都将产生一 5 | 个X的“循环”。即:分别将这两个整数的第1位数字与最后1位数字连在一起,可以得到一个相同的数 6 | 字循环;当然两个整数在该数字循环中的起始位置不同。例如,142857是一个循环数 7 | 142857 *1 = 142857 8 | 142857 *2 = 285714 9 | 142857 *3 = 428571 10 | 142857 *4 = 571428 11 | 142857 *5 = 714285 12 | 142857 *6 = 857142 13 | 14 | 关于输入 15 | 16 | 写一个程序判断一个整数是否是循环数。输入文件是一个整数序列,每个整数长度为2~60。注意:每 17 | 个整数前面的零被看作是该整数的一部分,在计算N时要统计。例如“01”是一个2位的整数,而“1” 18 | 是一个1位的整数。 19 | 20 | 关于输出 21 | 22 | 对每个输入整数,输出一行,说明该整数是否是循环数。 23 | 24 | 例子输入 25 | 26 | 142857 27 | 142856 28 | 142858 29 | 01 30 | 0588235294117647 31 | 32 | 例子输出 33 | 34 | 142857 is cyclic 35 | 142856 is not cyclic 36 | 142858 is not cyclic 37 | 01 is not cyclic 38 | 0588235294117647 is cyclic 39 | *****/ 40 | 41 | #include 42 | #include 43 | using namespace std; 44 | 45 | #define MAX_L 200 46 | 47 | char num[MAX_L] = "\0"; 48 | char mul[MAX_L] = "\0"; 49 | int l = 0; 50 | 51 | int main() 52 | { 53 | while (cin >> num) 54 | { 55 | bool is_cyclic = true; 56 | strcpy(mul, num); 57 | l = strlen(num); 58 | for (int _Y = 2; _Y <= l; _Y++) 59 | { 60 | int carry = 0, st = 0; 61 | bool found = false; 62 | if (!is_cyclic) 63 | break; 64 | for (int i = l - 1; i >= 0; i--) 65 | { 66 | mul[i] = num[i] - '0' + mul[i] - '0' + carry; 67 | carry = mul[i] / 10; 68 | mul[i] = mul[i] % 10 + '0'; 69 | } 70 | if (carry) 71 | { 72 | is_cyclic = false; 73 | break; 74 | } 75 | strncpy(mul + l, mul, l); 76 | for (int i = 0; i < l; i++) 77 | if (strncmp(mul + i, num, l) == 0) 78 | { 79 | found = true; 80 | break; 81 | } 82 | if (!found) 83 | { 84 | is_cyclic = false; 85 | break; 86 | } 87 | } 88 | if (is_cyclic) 89 | cout << num << " is cyclic" << endl; 90 | else 91 | cout << num << " is not cyclic" << endl; 92 | } 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /综合练习/ngram串频统计.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 描述 3 | 在文本分析中常用到n-gram串频统计方法,即,统计相邻的n 个单元(如单词、汉字、或者字符) 4 | 在整个文本中出现的频率。假设有一个字符串,请以字符为单位按n-gram 统计长度为n的子串出 5 | 现的频度,并输出最高频度以及频度最高的子串。设定所给的字符串不多于500个字符,且1 29 | #include 30 | using namespace std; 31 | 32 | #define MAX_N 10 33 | #define MAX_L 510 34 | 35 | char sub[MAX_L][MAX_N] = {'\0'}; 36 | int cnt[MAX_L] = {0}; 37 | char str[MAX_L] = "\0"; 38 | 39 | int main() 40 | { 41 | int n_sub = 0; 42 | int n = 0, l =0; 43 | 44 | cin >> n_sub; 45 | cin.get(); 46 | cin.getline(str, MAX_L); 47 | l = strlen(str); 48 | /* Count n-gram sub-sequences */ 49 | strncpy(sub[n], str, n_sub); 50 | cnt[n++] = 1; 51 | for (int i = 1; i <= l - n_sub; i++) 52 | { 53 | bool found = false; 54 | for (int j = 0; j < n; j++) 55 | if (strncmp(sub[j], str + i, n_sub) == 0) 56 | { 57 | cnt[j]++; 58 | found = true; 59 | break; 60 | } 61 | if (!found) 62 | { 63 | strncpy(sub[n], str + i, n_sub); 64 | cnt[n++] = 1; 65 | } 66 | } 67 | /* Sort n-gram sub-sequences */ 68 | for (int i = 1; i < n; i++) 69 | for (int j = 0; j < i; j++) 70 | if (cnt[i] > cnt[j]) 71 | { 72 | char tmp[MAX_N]; 73 | strncpy(tmp, sub[i], n_sub); 74 | strncpy(sub[i], sub[j], n_sub); 75 | strncpy(sub[j], tmp, n_sub); 76 | cnt[i] = cnt[i] ^ cnt[j]; 77 | cnt[j] = cnt[i] ^ cnt[j]; 78 | cnt[i] = cnt[i] ^ cnt[j]; 79 | } 80 | 81 | if (cnt[0] <= 1) 82 | cout << "NO"; 83 | else 84 | { 85 | cout << cnt[0] << endl; 86 | for (int i = 0; i < n && cnt[i] == cnt[0]; i++) 87 | cout << sub[i] << endl; 88 | } 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /第三阶段编程练习5/最优路径.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 给定一个n*m的方格棋盘,第i行第j列的方格价值为W(i, j)。现在你从第一行的任选方格出发,可以选择向南、 5 | 向西或者向东走,但是不能重复经过相同的格子(即不能走回头路),一直到第n行的任意一个方格为止。 6 | 请你设计一条路径,使得从开始到结束所经过的所有方格的价值和最大。 7 | 8 | 关于输入 9 | 10 | 输入包含多组数据。 11 | 每组数据第一行为两个整数n和m(1<=n, m<=200),表示棋盘大小。下接一个n*m的整数矩阵,描述价值矩阵, 12 | W(i,j)在[-1000, 1000]之内。 13 | 14 | 关于输出 15 | 16 | 对于每一组数据,输出一个整数,表示最大的价值。 17 | 18 | 例子输入 19 | 20 | 2 1 21 | 100 22 | -101 23 | 4 4 24 | 1 -5 20 3 25 | 3 2 -50 20 26 | 3 3 3 3 27 | 9 -100 0 17 28 | 29 | 例子输出 30 | 31 | -1 32 | 66 33 | 34 | 提示信息 35 | 36 | 样例第二组数据最优路径是(1,3)-(1,4)-(2,4)-(3,4)-(3,3)-(4,3)-(4,4) 37 | *****/ 38 | 39 | #include 40 | #include 41 | using namespace std; 42 | 43 | #define MAX_N 300 44 | #define MIN_INT 0x80000000 45 | 46 | /** 47 | 思路:动态规划 48 | 49 | 简单分析问题可以发现,在每一行row(下标从1开始)内的得分都只能是由row[j]到row[k]的连续的一段的和。 50 | 为了后面能方便地计算row中任意一段的和,我们构造前缀和数组psum。 51 | psum[i]表示从row[0]加到row[i]的和,那么对row中任意的j到k一段(0 < j <= k),其和就是psum[k] - psum[j-1]。 52 | 进一步地,我们可以发现根本没有必要存储整个矩阵,而是直接存储每一行的psum数组即可。 53 | 因此,我们用psum[i][j]表示矩阵第i行(从1开始)的长度为j的前缀和。psum[i][0]总是0。 54 | 55 | 用dp[i][j]表示第i行走完之后在第j个位置停下后能获得的最大分数。 56 | 我们可以从i-1行的任意k位置尝试,向下一行后径直走到j位置,在其中取分数最大的方案作为dp[i][j]。 57 | 这一过程中,dp[i-1][k]假设已知,在第i行的得分为psum[i][max(j, k)] - psum[i][min(j, k)-1]。 58 | 最后只需要考虑起始的边界条件即可——很显然dp[0][j]总是0,因为此时在第0行,还没有进入矩阵。 59 | 自上而下计算完dp数组后,扫描第n行找到最大值即为所需答案。 60 | **/ 61 | 62 | int n = 0, m = 0; 63 | int psum[MAX_N][MAX_N] = {0}; 64 | int dp[MAX_N][MAX_N] = {0}; 65 | 66 | int main() 67 | { 68 | int num = 0; 69 | while (cin >> n >> m) 70 | { 71 | for (int i = 1; i <= n; i++) 72 | for (int j = 1; j <= m; j++) 73 | { 74 | cin >> psum[i][j]; 75 | psum[i][j] += psum[i][j - 1]; 76 | } 77 | for (int i = 1; i <= n; i++) 78 | for (int j = 1; j <= m; j++) 79 | { 80 | dp[i][j] = MIN_INT; 81 | for (int k = 1; k <= m; k++) 82 | { 83 | num = psum[i][max(j, k)] - psum[i][min(j, k) - 1]; 84 | dp[i][j] = max(dp[i][j], dp[i - 1][k] + num); 85 | } 86 | } 87 | num = MIN_INT; 88 | for (int j = 1; j <= m; j++) 89 | num = max(num, dp[n][j]); 90 | cout << num << endl; 91 | } 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /第四阶段编程练习2/循环数.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 当一个N位的整数X满足下列条件时,称其为循环数:X与任意一个整数1≤Y ≤ N相乘时,都将产生一 5 | 个X的“循环”。即:分别将这两个整数的第1位数字与最后1位数字连在一起,可以得到一个相同的数 6 | 字循环;当然两个整数在该数字循环中的起始位置不同。例如,142857是一个循环数 7 | 142857 *1 = 142857 8 | 142857 *2 = 285714 9 | 142857 *3 = 428571 10 | 142857 *4 = 571428 11 | 142857 *5 = 714285 12 | 142857 *6 = 857142 13 | 14 | 关于输入 15 | 16 | 写一个程序判断一个整数是否是循环数。输入文件是一个整数序列,每个整数长度为2~60。注意:每 17 | 个整数前面的零被看作是该整数的一部分,在计算N时要统计。例如“01”是一个2位的整数,而“1” 18 | 是一个1位的整数。 19 | 20 | 关于输出 21 | 22 | 对每个输入整数,输出一行,说明该整数是否是循环数。 23 | 24 | 例子输入 25 | 26 | 142857 27 | 142856 28 | 142858 29 | 01 30 | 0588235294117647 31 | 32 | 例子输出 33 | 34 | 142857 is cyclic 35 | 142856 is not cyclic 36 | 142858 is not cyclic 37 | 01 is not cyclic 38 | 0588235294117647 is cyclic 39 | *****/ 40 | 41 | #include 42 | #include 43 | using namespace std; 44 | 45 | #define MAX_L 200 46 | 47 | char num[MAX_L] = "\0"; 48 | char mul[MAX_L] = "\0"; 49 | int l = 0; 50 | 51 | int main() 52 | { 53 | while (cin >> num) 54 | { 55 | bool is_cyclic = true; 56 | strcpy(mul, num); 57 | l = strlen(num); 58 | for (int _Y = 2; _Y <= l; _Y++) // mul为num的倍数,从2倍起进行计算 59 | { 60 | int carry = 0, st = 0; 61 | bool found = false; 62 | if (!is_cyclic) 63 | break; 64 | for (int i = l - 1; i >= 0; i--) 65 | { 66 | mul[i] = num[i] - '0' + mul[i] - '0' + carry; 67 | carry = mul[i] / 10; 68 | mul[i] = mul[i] % 10 + '0'; 69 | } 70 | // cout << mul << endl; 71 | if (carry) 72 | { 73 | is_cyclic = false; 74 | break; 75 | } 76 | strncpy(mul + l, mul, l); // 复制mul置于mul后 77 | for (int i = 0; i < l; i++) // 逐个检查mul+i与num的长度为l的串是否相同 78 | if (strncmp(mul + i, num, l) == 0) 79 | { 80 | found = true; 81 | break; 82 | } 83 | if (!found) 84 | { 85 | is_cyclic = false; 86 | break; 87 | } 88 | } 89 | if (is_cyclic) 90 | cout << num << " is cyclic" << endl; 91 | else 92 | cout << num << " is not cyclic" << endl; 93 | } 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /综合练习/有效地密码.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 由于北大未名BBS比较知名,容易引来黑客攻击。因此,对每个人的账户而言, 4 | 密码越复杂,被黑客破解的可能性就越低。通常而言,密码至少由不少于六个 5 | 字符组成,由以下规则判定密码是否安全: 6 | 1. 如果密码长度小于6位,则不安全 7 | 2. 如果组成密码的字符只有一类,则不安全 8 | 3. 如果组成密码的字符有两类,则为中度安全 9 | 4. 如果组成密码的字符有三类或以上,则为安全 10 | 通常,把数字、大写字母、小写字母和其它符号归为四类不同的字符。 11 | 关于输入 12 | 输入的第一行是一个整数n,表明后面有n组密码输入。随后的n行每行代表一 13 | 个密码,每个密码的长度均小于50个字符(不含空格)。 14 | 关于输出 15 | 针对每一个密码判断并输出它是否安全。对于不安全的密码输出"Not safe", 16 | 对于中度安全的密码输出"Medium safe",对于安全的密码输出"Safe" 17 | 例子输入 18 | 5 19 | 1234 20 | abcdefg 21 | 123safe 22 | 432*fe+93 23 | AD7doiuo31 24 | 例子输出 25 | Not safe 26 | Not safe 27 | Medium safe 28 | Safe 29 | Safe 30 | *****/ 31 | 32 | #include 33 | using namespace std; 34 | 35 | #define MAX_LEN 100 36 | 37 | enum CharType 38 | { 39 | NUMBER = 0, 40 | LOWER, 41 | UPPER, 42 | OTHER, 43 | CHAR_TYPE_COUNT 44 | }; 45 | 46 | enum SafeLevel 47 | { 48 | NOT_SAFE, 49 | MEDIUM_SAFE, 50 | SAFE 51 | }; 52 | 53 | CharType getCharType(char c) 54 | { 55 | if (c >= '0' && c <= '9') 56 | return NUMBER; 57 | if (c >= 'a' && c <= 'z') 58 | return LOWER; 59 | if (c >= 'A' && c <= 'Z') 60 | return UPPER; 61 | return OTHER; 62 | } 63 | 64 | SafeLevel getSafeLevel(char* str) 65 | { 66 | bool type[CHAR_TYPE_COUNT] = {false}; 67 | int cnt = 0, l = 0; 68 | for (l = 0; str[l] != '\0'; l++) 69 | type[getCharType(str[l])] = true; 70 | if (l < 6) 71 | return NOT_SAFE; 72 | for (int i = 0; i < CHAR_TYPE_COUNT; i++) 73 | if (type[i]) 74 | cnt++; 75 | switch(cnt) 76 | { 77 | case 1: return NOT_SAFE; 78 | case 2: return MEDIUM_SAFE; 79 | default: return SAFE; 80 | } 81 | } 82 | 83 | int main() 84 | { 85 | int n = 0; 86 | char password[MAX_LEN] = ""; 87 | cin >> n; 88 | while(n--) 89 | { 90 | cin >> password; 91 | switch(getSafeLevel(password)) 92 | { 93 | case NOT_SAFE: 94 | cout << "Not safe" << endl; 95 | break; 96 | case MEDIUM_SAFE: 97 | cout << "Medium safe" << endl; 98 | break; 99 | case SAFE: 100 | cout << "Safe" << endl; 101 | break; 102 | default: break; 103 | } 104 | } 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /第三阶段编程练习4/分词.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 给定一个包含n个单词的英文词典和m个只由英文字母组成的字符串。 5 | 判断这些字符串能否由词典中的单词组成。 6 | 比如词典中包含5个单词:"Jim", "and", "cat","like", "dog" 7 | 这些单词能组成"Jimlikecatanddog"、"doglikecatandcatlikedog"等, 8 | 但是不能组成"catlikeme" 9 | 为了简化问题,所有的字母都是小写,而且词典中的所有单词长度都一样。 10 | 11 | 关于输入 12 | 13 | 第一行两个正整数,n和m(n,m都不超过100); 14 | 接下来n行,每行一个单词,每个单词长度不超过20; 15 | 接下来m行,每行一个字符串,长度不超过1000; 16 | 17 | 关于输出 18 | 19 | m行,表示词库中的单词能否组成该字符串,能输出"Yes",不能输出"No"。 20 | 21 | 例子输入 22 | 23 | 10 5 24 | did 25 | not 26 | and 27 | but 28 | hit 29 | run 30 | cat 31 | dog 32 | pig 33 | cow 34 | cathitdoganddogrun 35 | doghitpigbutpigdidnotrun 36 | pighitcowandcowdidrun 37 | cowhitcatandcatcry 38 | catdogpigandcowarehungry 39 | 40 | 例子输出 41 | 42 | Yes 43 | Yes 44 | Yes 45 | No 46 | No 47 | *****/ 48 | 49 | #include 50 | #include 51 | #include 52 | using namespace std; 53 | 54 | #define MAX_N 110 55 | #define MAX_WORD_L 30 56 | #define MAX_L 1100 57 | 58 | char* dict[MAX_N] = {NULL}; // 字典,使用指针方便排序 59 | int n_dict = 0, l = 0; // n_dict为字典大小,l为单词长度 60 | 61 | /** 对比函数,用于字符串排序 **/ 62 | bool cmp(char* a, char* b) 63 | { 64 | return strncmp(a, b, l) < 0; 65 | } 66 | 67 | /** 深度优先搜索,判断是否可以分词 **/ 68 | bool dfs(char* s) 69 | { 70 | int c = 0; 71 | if (s[0] == '\0') // 若s已经是空字符串 72 | return true; // 说明分词结束,返回true 73 | for (int i = 0; i < n_dict; i++) // 遍历dict 74 | { 75 | c = strncmp(s, dict[i], l); // 比对s和c的前l个字符 76 | if (!c) // 若c为0,则相等 77 | return dfs(s + l); // 分词,递归深搜 78 | else if (c < 0) // 若c小于0,则dict后面也不可能出现可能的分词 79 | return false; // 直接返回false 80 | } 81 | return false; 82 | } 83 | 84 | int main() 85 | { 86 | int m = 0; 87 | char str[MAX_L] = ""; 88 | 89 | /** 输入字典并排序 **/ 90 | cin >> n_dict >> m; 91 | for (int i = 0; i < n_dict; i++) 92 | { 93 | dict[i] = new char[MAX_WORD_L]; 94 | cin >> dict[i]; 95 | } 96 | l = strlen(dict[0]); 97 | sort(dict, dict + n_dict, cmp); 98 | 99 | while (m--) 100 | { 101 | cin >> str; 102 | if (dfs(str)) 103 | cout << "Yes" < 47 | #include 48 | using namespace std; 49 | 50 | #define MAXN 110 51 | #define ND 4 52 | 53 | const int dr[ND] = {0, 0, 1, -1}; 54 | const int dc[ND] = {1, -1, 0, 0}; 55 | 56 | int mask[MAXN][MAXN] = {0}; 57 | int sick[2][MAXN][MAXN] = {0}, cur = 0, nxt = 1; 58 | int n = 0; 59 | 60 | int main() 61 | { 62 | int r = 0, c = 0, d = 0; 63 | int ans = 0; 64 | cin >> n; 65 | for (int i = 1; i <= n; i++) 66 | for (int j = 1; j <= n; j++) 67 | cin >> mask[i][j]; 68 | cin >> r >> c >> d; 69 | r++; 70 | c++; 71 | sick[cur][r][c] = 1; 72 | while (d--) 73 | { 74 | memset(sick + nxt, 0x00, sizeof(int) * MAXN * MAXN); 75 | for (int i = 1; i <= n; i++) 76 | for (int j = 1; j <= n; j++) 77 | if (sick[cur][i][j] && !mask[i][j]) 78 | for (int d = 0; d < ND; d++) 79 | sick[nxt][i + dr[d]][j + dc[d]]++; 80 | for (int i = 1; i <= n; i++) 81 | for (int j = 1; j <= n; j++) 82 | if ((!mask[i][j] && sick[nxt][i][j]) || 83 | (mask[i][j] && sick[nxt][i][j] == ND) || 84 | sick[cur][i][j]) 85 | sick[nxt][i][j] = 1; 86 | else 87 | sick[nxt][i][j] = 0; 88 | nxt = 1 - nxt; 89 | cur = 1 - cur; 90 | } 91 | for (int i = 1; i <= n; i++) 92 | for (int j = 1; j <= n; j++) 93 | ans += sick[cur][i][j]; 94 | cout << ans << endl; 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /第三阶段编程练习3/水淹七军.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 随着最后通牒的递出,C国的总攻也开始了,由于C国在地形上的优势,C国总司令下令采用水攻,剿灭A国最后的有生力量。 5 | 地形图是一个M*N的矩阵,矩阵上每一个点都对应着当前点的高度。C国总司令将选择若干个点进行放水(放水……这个词很 6 | 好很强大嘛……)。根据水往低处流的特性,水可以往四个方向的流动,被淹的地方的水面高度便和放水点的高度一样。然 7 | 而,A国不是一马平川的,所以总会有地方是淹没不到的。你的任务很简单,判断一下A国司令部会不会被淹没掉。 8 | 我们将给你完整的地形图,然后给出A国司令部所在位置,给出C国将在哪几个点进行放水操作。你所需要的,就是给出A国 9 | 司令部会不会被水淹。如果被水淹了,那么就意味着,战争结束了,否则,战争也会结束(八成被水包围了)…… 10 | 11 | 关于输入 12 | 13 | 第一行:一个整数K,代表数据组数。 14 | 对于每一组数据: 15 | 第1行:符合题目描述的两个整数,M(0 < M <= 200)、N(0 < N <= 200)。 16 | 第2行至M+1行:每行N个数,以空格分开,代表这个矩阵上的各点的高度值H(0<=H<=1000)。 17 | 第M+2行:两个整数I(0 < I <= M)、J(0 < J <= N),代表司令部所在位置。 18 | 第M+3行:一个整数P(0 < P <= M * N),代表放水点个数。 19 | 第M+4行至M+P+4行:每行两个整数X(0 < X <= M)、Y(0 < Y <= N),代表放水点。 20 | 21 | 关于输出 22 | 23 | 对于每组数据,输出一行,如果被淹则输出Yes,没有则输出No。 24 | 25 | 例子输入 26 | 27 | 1 28 | 5 5 29 | 1 1 1 1 1 30 | 1 0 0 0 1 31 | 1 0 1 0 1 32 | 1 0 0 0 1 33 | 1 1 1 1 1 34 | 3 3 35 | 2 36 | 1 1 37 | 2 2 38 | 39 | 例子输出 40 | 41 | Yes 42 | *****/ 43 | 44 | #include 45 | #include 46 | using namespace std; 47 | 48 | #define MAX_N 1000 49 | #define ND 4 50 | 51 | int arr[MAX_N][MAX_N] = {}; // 高度矩阵 52 | bool visit[MAX_N][MAX_N] = {}; // 记录各个位置是否淹没的矩阵 53 | int m = 0, n = 0; // 棋盘大小 54 | int tr = 0, tc = 0; // 司令部位置 55 | int dr[ND] = {0, 0, 1, -1}, dc[ND] = {1, -1, 0, 0}; // 水流动的方向 56 | 57 | /** 深度优先搜索 **/ 58 | void dfs(int sr, int sc, int h) 59 | { 60 | if (sr <= 0 || sc <= 0 || sr > m || sc > n) // 非法位置 61 | return; // 终止 62 | if (arr[sr][sc] > h) // 当前位置高于放水高度 63 | return; // 终止 64 | if (visit[sr][sc]) // 当前位置已经被淹没 65 | return; // 终止 66 | visit[sr][sc] = true; // 淹没当前位置 67 | for (int d = 0; d < ND; d++) 68 | dfs(sr + dr[d], sc + dc[d], h); // 向所有方向搜索 69 | } 70 | 71 | int main() 72 | { 73 | int _n = 0, n_spot = 0; 74 | int r = 0, c = 0; 75 | cin >> _n; 76 | while (_n--) 77 | { 78 | memset(visit, 0x00, sizeof(visit)); 79 | 80 | cin >> m >> n; 81 | for (int i = 1; i <= m; i++) 82 | for (int j = 1; j <= n; j++) 83 | cin >> arr[i][j]; 84 | cin >> tr >> tc >> n_spot; 85 | while (n_spot--) 86 | { 87 | cin >> r >> c; 88 | dfs(r, c, arr[r][c]); 89 | } 90 | if (visit[tr][tc]) 91 | cout << "Yes" << endl; 92 | else 93 | cout << "No" << endl; 94 | } 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /2020年期末考试题/拼装模型.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | Dzx从日本回来了,并为TN准备了礼物----一个恐龙模型。TN想把它尽快拼好,但是由于模型很庞大, 5 | TN又实在比较懒,所以他希望你为他寻找一个最节省时间的拼装方案。 6 | 模型是由N个零件组成的,每次TN可以选取两个零件拼装在一起来组成一个新的零件,直到得到完整的 7 | 模型。由于零件的复杂程度不同,TN每次拼装所需要的时间也是不同的,对于两个零件A和B,假设他 8 | 们的复杂程度分别为a和b,则TN要将这两个零件拼装在一起所需要的时间为a+b,而这由两个零件所组 9 | 成的新零件的复杂程度为a+b。 10 | 现在TN已经统计出了每个零件的复杂程度,你能告诉他最快的拼装方法需要多少时间么? 11 | 12 | 关于输入 13 | 14 | Line 1: N (1 <= N <= 10000),零件数目 15 | Line 2: N Integers,表示每个零件的复杂程度 16 | 17 | 关于输出 18 | 19 | 最快的拼装方案所需要的时间 20 | 21 | 例子输入 22 | 23 | 3 24 | 1 2 9 25 | 26 | 例子输出 27 | 28 | 15 29 | 30 | 提示信息 31 | 32 | 每次都选择当前最小的两个零件。 33 | *****/ 34 | 35 | #include 36 | using namespace std; 37 | 38 | #define LEFT(x) (x)*2+1 // Left child index of x 39 | #define RIGHT(x) (x)*2+2 // Right child index of x 40 | #define PARENT(x) (x-1)/2 // Parent index of x 41 | 42 | #define HEAP_SIZE 200200 43 | #define HEAP_BOTTOM 0x80000000 44 | 45 | int heap[HEAP_SIZE] = {0}; // min_heap, where parent <= left and parent <= right 46 | int _size = 0; 47 | 48 | void swap_heap(int i, int j) 49 | { 50 | int tmp = heap[j]; 51 | heap[j] = heap[i]; 52 | heap[i] = tmp; 53 | } 54 | 55 | void push_heap(int num) 56 | { 57 | int i = _size; 58 | heap[_size++] = num; 59 | while(i > 0 && heap[i] < heap[PARENT(i)]) 60 | { 61 | swap_heap(i, PARENT(i)); 62 | i = PARENT(i); 63 | } 64 | } 65 | 66 | void min_heap(int i) 67 | { 68 | int l = LEFT(i), r = RIGHT(i), small = i; 69 | if (l < _size && heap[l] < heap[small]) 70 | small = l; 71 | if (r < _size && heap[r] < heap[small]) 72 | small = r; 73 | if (i != small) 74 | { 75 | swap_heap(i, small); 76 | min_heap(small); 77 | } 78 | } 79 | 80 | void create_heap() 81 | { 82 | for (int i = PARENT(_size - 1); i >= 0; i--) 83 | min_heap(i); 84 | } 85 | 86 | int pop_heap() 87 | { 88 | if (!_size) 89 | return HEAP_BOTTOM; 90 | _size--; 91 | int r = heap[0]; 92 | swap_heap(0, _size); 93 | min_heap(0); 94 | return r; 95 | } 96 | 97 | int main() 98 | { 99 | int ans = 0, t = 0; 100 | cin >> _size; 101 | for (int i = 0; i < _size; i++) 102 | cin >> heap[i]; 103 | create_heap(); 104 | while (_size > 1) 105 | { 106 | t = pop_heap() + pop_heap(); 107 | ans += t; 108 | push_heap(t); 109 | } 110 | cout << ans << endl; 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /第三阶段编程练习4/图案计数.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 一张画布里有n行*m列个格子,其中有的格子里有颜色填充,有的格子是空的没有颜色填充。 5 | 现在需要你写一个程序来数出画布里边有颜色填充的格子构成了多少个图案,其中图案的定 6 | 义为: 7 | 如果两个有颜色的格子边相邻或者角相邻(即横、纵两个方向上的位置差都不超过1),则 8 | 他们属于同一个图案。 9 | 10 | 关于输入 11 | 12 | 第一行为两个整数n和m(1<=n, m<=200)。 13 | 之后的n行,每行为一个长度为m的字符串,构成了整个画布。字符串中,#表示颜色,-表示空白。 14 | 15 | 关于输出 16 | 17 | 一个整数,表示图案的个数 18 | 19 | 例子输入 20 | 21 | 19 48 22 | ------------------------------------------------ 23 | ---####-----#-----#----------------------####--- 24 | --######----#-----#---------------------######-- 25 | -########--#-#---#-#####--#-##-##---#--########- 26 | -###--###--#-#---#-#----#-##-##--#--#--###--###- 27 | -###--###--#--#-#--######-#--#---#-#---###--###- 28 | -########--#--#-#--#------#--#----##---########- 29 | --######---#---#---######-#--#-----#----######-- 30 | ---####----------------------------#-----####--- 31 | ----------------------------------#------------- 32 | ------------------------------------------------ 33 | ---###--#--------#------#----------------------- 34 | --#---#-#---------------#----------------------- 35 | -#------#-##--#-##--##-###-#-##-###--###-#--##-- 36 | -#------##--#-##-#-#----#--##--#---##---##-#---- 37 | -#------#---#-#--#--#---#--#---#---##----#--#--- 38 | --#---#-#---#-#--#---#--#--#---#---##---##---#-- 39 | ---###--#---#-#--#-##---#--#---#---#-###-#-##--- 40 | ------------------------------------------------ 41 | 42 | 例子输出 43 | 44 | 12 45 | *****/ 46 | 47 | #include 48 | #include 49 | using namespace std; 50 | 51 | #define MAX_N 300 52 | #define COLOR '#' 53 | #define EMPTY '-' 54 | #define ND 8 55 | 56 | char arr[MAX_N][MAX_N] = {""}; 57 | int row = 0, col = 0; 58 | int dr[ND] = {0, 0, 1, -1, 1, 1, -1, -1}; 59 | int dc[ND] = {1, -1, 0, 0, 1, -1, 1, -1}; 60 | 61 | /** 深度优先搜索,移除当前图案 **/ 62 | void dfs(int r, int c) 63 | { 64 | if (arr[r][c] == EMPTY) 65 | return; 66 | arr[r][c] = EMPTY; 67 | for (int d = 0; d < ND; d++) 68 | dfs(r + dr[d], c + dc[d]); 69 | } 70 | 71 | int main() 72 | { 73 | int cnt = 0; 74 | cin >> row >> col; 75 | memset(arr, EMPTY, sizeof(arr)); 76 | for (int i = 1; i <= row; i++) 77 | for (int j = 1; j <= col; j++) 78 | cin >> arr[i][j]; 79 | for (int i = 1; i <= row; i++) 80 | for (int j = 1; j <= col; j++) 81 | if (arr[i][j] == COLOR) // 每当遇到颜色图案 82 | { 83 | cnt++; // 图案计数加一 84 | dfs(i, j); // 移除该图案 85 | } 86 | cout << cnt << endl; 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /综合练习/人工智能.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 人工智能一直是计算机学所追求的一个很高的境界,全世界的计算机学家们至今仍在不断努力力求达到 5 | 这个境界。 6 | 这道题也跟“人工智能”有关。 7 | 学过初中物理的同学都应该知道物理学中的这个公式P(功率)= U(电压)* I(电流)。如果给定其 8 | 中的任意两个值,第三个值都是很容易求的,这个就是本题的任务。 9 | 10 | 关于输入 11 | 12 | 既然是人工智能,不要妄想题目会直接告诉你其中的某两个值。 13 | 输入的第一行是一个整数,表示有多少组测试数据。以下每一行是一组测试数据,分别为一句英文句子。 14 | 你需要从中识别已知和未知,并且求出未知量。需要说明的是,句子中I,U,P三个物理量中已知的两 15 | 个一定会以I=xA, U=xV,P=xW这样的样式给出(注意单位以及大小写)。在这样的表达式中,可能会 16 | 在单位(A,V,W)的前面出现表示数量级的字母m、k、M,分别表示毫,千,兆。 17 | 18 | 关于输出 19 | 20 | 对于每一组数据,按以下格式输出三行: 21 | 首先输出"Problem #k",k表示当前是第k组测试数据。 22 | 然后在下一行输出结果,结果要求单位必须为A,V或者W,并且保留两位小数。 23 | 最后再输出一个空行。 24 | 具体可以参见样例输出。 25 | 26 | 例子输入 27 | 28 | 3 29 | If the voltage is U=200V and the current is I=4.5A, which power is generated? 30 | A light-bulb yields P=100W and the voltage is U=220V. Compute the current, please. 31 | bla bla bla lightning strike I=2A bla bla bla P=2.5MW bla bla voltage? 32 | 33 | 例子输出 34 | 35 | Problem #1 36 | P=900.00W 37 | 38 | Problem #2 39 | I=0.45A 40 | 41 | Problem #3 42 | U=1250000.00V 43 | 44 | 提示信息 45 | 46 | 提示:数字后面的m、k、M,分别代表0.001, 1000,1000000. 47 | 例如:2m = 2 * 0.001 48 | *****/ 49 | 50 | #include 51 | #include 52 | using namespace std; 53 | 54 | double get_value() 55 | { 56 | double val = 0; 57 | char c = '\0'; 58 | cin >> val; 59 | c = cin.get(); 60 | switch(c) 61 | { 62 | case 'm': return val * 0.001; 63 | case 'k': return val * 1000; 64 | case 'M': return val * 1000000; 65 | default: return val; 66 | } 67 | } 68 | 69 | int main() 70 | { 71 | int n; 72 | cin >> n; cin.get(); 73 | for (int _case = 1; _case <= n; _case++) 74 | { 75 | double P = -1, U = -1, I = -1; 76 | char c = '\0', last_c = '\0'; 77 | while (c = cin.get()) 78 | { 79 | if (c == '\n') 80 | break; 81 | if (c == '=' && last_c == 'I') 82 | I = get_value(); 83 | if (c == '=' && last_c == 'U') 84 | U = get_value(); 85 | if (c == '=' && last_c == 'P') 86 | P = get_value(); 87 | last_c = c; 88 | } 89 | cout << "Problem #" << _case << endl; 90 | if (P < 0) 91 | cout << "P=" << fixed << setprecision(2) << U * I << "W" << endl << endl; 92 | else if (I < 0) 93 | cout << "I=" << fixed << setprecision(2) << P / U << "A" << endl << endl; 94 | else 95 | cout << "U=" << fixed << setprecision(2) << P / I << "V" << endl << endl; 96 | } 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /第四阶段编程练习2/人工智能.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 人工智能一直是计算机学所追求的一个很高的境界,全世界的计算机学家们至今仍在不断努力力求达到 5 | 这个境界。 6 | 这道题也跟“人工智能”有关。 7 | 学过初中物理的同学都应该知道物理学中的这个公式P(功率)= U(电压)* I(电流)。如果给定其 8 | 中的任意两个值,第三个值都是很容易求的,这个就是本题的任务。 9 | 10 | 关于输入 11 | 12 | 既然是人工智能,不要妄想题目会直接告诉你其中的某两个值。 13 | 输入的第一行是一个整数,表示有多少组测试数据。以下每一行是一组测试数据,分别为一句英文句子。 14 | 你需要从中识别已知和未知,并且求出未知量。需要说明的是,句子中I,U,P三个物理量中已知的两 15 | 个一定会以I=xA, U=xV,P=xW这样的样式给出(注意单位以及大小写)。在这样的表达式中,可能会 16 | 在单位(A,V,W)的前面出现表示数量级的字母m、k、M,分别表示毫,千,兆。 17 | 18 | 关于输出 19 | 20 | 对于每一组数据,按以下格式输出三行: 21 | 首先输出"Problem #k",k表示当前是第k组测试数据。 22 | 然后在下一行输出结果,结果要求单位必须为A,V或者W,并且保留两位小数。 23 | 最后再输出一个空行。 24 | 具体可以参见样例输出。 25 | 26 | 例子输入 27 | 28 | 3 29 | If the voltage is U=200V and the current is I=4.5A, which power is generated? 30 | A light-bulb yields P=100W and the voltage is U=220V. Compute the current, please. 31 | bla bla bla lightning strike I=2A bla bla bla P=2.5MW bla bla voltage? 32 | 33 | 例子输出 34 | 35 | Problem #1 36 | P=900.00W 37 | 38 | Problem #2 39 | I=0.45A 40 | 41 | Problem #3 42 | U=1250000.00V 43 | 44 | 提示信息 45 | 46 | 提示:数字后面的m、k、M,分别代表0.001, 1000,1000000. 47 | 例如:2m = 2 * 0.001 48 | *****/ 49 | 50 | #include 51 | #include 52 | using namespace std; 53 | 54 | double get_value() 55 | { 56 | double val = 0; 57 | char c = '\0'; 58 | cin >> val; 59 | c = cin.get(); 60 | switch(c) 61 | { 62 | case 'm': return val * 0.001; 63 | case 'k': return val * 1000; 64 | case 'M': return val * 1000000; 65 | default: return val; 66 | } 67 | } 68 | 69 | int main() 70 | { 71 | int n; 72 | cin >> n; cin.get(); 73 | for (int _case = 1; _case <= n; _case++) 74 | { 75 | double P = -1, U = -1, I = -1; 76 | char c = '\0', last_c = '\0'; 77 | while (c = cin.get()) 78 | { 79 | if (c == '\n') 80 | break; 81 | if (c == '=' && last_c == 'I') 82 | I = get_value(); 83 | if (c == '=' && last_c == 'U') 84 | U = get_value(); 85 | if (c == '=' && last_c == 'P') 86 | P = get_value(); 87 | last_c = c; 88 | } 89 | cout << "Problem #" << _case << endl; 90 | if (P < 0) 91 | cout << "P=" << fixed << setprecision(2) << U * I << "W" << endl << endl; 92 | else if (I < 0) 93 | cout << "I=" << fixed << setprecision(2) << P / U << "A" << endl << endl; 94 | else 95 | cout << "U=" << fixed << setprecision(2) << P / I << "V" << endl << endl; 96 | } 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /第三阶段编程练习3/棋盘问题.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在 5 | 棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。 6 | 7 | 关于输入 8 | 9 | 输入含有多组测试数据。 10 | 每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数 11 | 目。 n <= 8 , k <= n 12 | 当为-1 -1时表示输入结束。 13 | 随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空 14 | 白行或者空白列)。 15 | 16 | 关于输出 17 | 18 | 对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。 19 | 20 | 例子输入 21 | 22 | 2 1 23 | #. 24 | .# 25 | 4 4 26 | ...# 27 | ..#. 28 | .#.. 29 | #... 30 | -1 -1 31 | 32 | 例子输出 33 | 34 | 2 35 | 1 36 | *****/ 37 | 38 | #include 39 | #include 40 | using namespace std; 41 | 42 | #define MAX_N 10 43 | #define AVAILABLE '#' 44 | #define EMPTY '.' 45 | 46 | char board[MAX_N][MAX_N] = {""}; // 棋盘 47 | int n = 0, ans = 0; // n为棋盘大小,ans为搜索结果 48 | bool r[MAX_N] = {false}, c[MAX_N] = {false}; // 记录行(r)或列(c)是否放过棋子 49 | int x[MAX_N * MAX_N] = {0}, y[MAX_N * MAX_N] = {0}, n_available = 0; // 记录棋盘上所有可行位置 50 | 51 | /** 深度优先搜索 **/ 52 | void dfs (int step,int chess) // step记录搜索到哪个可行位置,chess记录还有几个棋子要放 53 | { 54 | if (chess <= 0) // 若没有棋子要放了 55 | { 56 | ans++; // 则找到一种可行的放置方案,ans加1 57 | return; // 返回 58 | } 59 | if (step >= n_available) // 若没有可行位置了 60 | return; // 则直接返回 61 | 62 | dfs(step + 1, chess); // step位置不放,向后搜索 63 | if (!r[x[step]] && !c[y[step]]) // 若step位置可以放置 64 | { 65 | r[x[step]] = true; // 则先设置r和c的标签 66 | c[y[step]] = true; 67 | dfs(step + 1, chess - 1); // 向后搜索 68 | r[x[step]] = false; // 搜索结束后,恢复r和c的标签 69 | c[y[step]] = false; 70 | } 71 | } 72 | int main () 73 | { 74 | int k = 0; 75 | while (cin >> n >> k) 76 | { 77 | if (n < 0 && k < 0) 78 | return 0; 79 | 80 | /** 初始化 **/ 81 | memset(x, 0, sizeof(x)); 82 | memset(y, 0, sizeof(y)); 83 | memset(r, 0, sizeof(r)); 84 | memset(c, 0, sizeof(c)); 85 | ans = 0; 86 | n_available = 0; 87 | 88 | /** 读入棋盘,记录所有可行的位置 **/ 89 | for (int i = 0;i < n; i++) 90 | for (int j = 0;j < n; j++) 91 | { 92 | cin >> board[i][j]; 93 | if (board[i][j] == AVAILABLE) 94 | { 95 | x[n_available] = i; 96 | y[n_available++] = j; 97 | } 98 | } 99 | 100 | /** 深度优先搜索 **/ 101 | dfs(0, k); 102 | cout << ans << endl; 103 | } 104 | return 0; 105 | } 106 | -------------------------------------------------------------------------------- /第三阶段编程练习5/鸡蛋的硬度.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 最近XX公司举办了一个奇怪的比赛:鸡蛋硬度之王争霸赛。参赛者是来自世 界各地的母鸡,比赛的内容是看谁下的蛋最硬, 5 | 更奇怪的是XX公司并不使用什么精密仪器来测量蛋的硬度,他们采用了一种最老土的办法--从高度扔鸡蛋--来 测试鸡蛋的硬 6 | 度,如果一次母鸡下的蛋从高楼的第a层摔下来没摔破,但是从a+1层摔下来时摔破了,那么就说这只母鸡的鸡蛋的硬度是a。 7 | 你当然可以找出各种 理由说明这种方法不科学,比如同一只母鸡下的蛋硬度可能不一样等等,但是这不影响XX公司的争霸赛, 8 | 因为他们只是为了吸引大家的眼球,一个个鸡蛋从100 层的高楼上掉下来的时候,这情景还是能吸引很多人驻足观看的,当 9 | 然,XX公司也绝不会忘记在高楼上挂一条幅,写上“XX公司”的字样--这比赛不过是XX 公司的一个另类广告而已。 10 | 勤于思考的小A总是能从一件事情中发现一个数学问题,这件事也不例外。“假如有很多同样硬度的鸡蛋,那么我可以用二分 11 | 的办法用最少的次数测出鸡蛋 的硬度”,小A对自己的这个结论感到很满意,不过很快麻烦来了,“但是,假如我的鸡蛋不 12 | 够用呢,比如我只有1个鸡蛋,那么我就不得不从第1层楼开始一层一 层的扔,最坏情况下我要扔100次。如果有2个鸡蛋, 13 | 那么就从2层楼开始的地方扔……等等,不对,好像应该从1/3的地方开始扔才对,嗯,好像也不一定 啊……3个鸡蛋怎么办, 14 | 4个,5个,更多呢……”,和往常一样,小A又陷入了一个思维僵局,与其说他是勤于思考,不如说他是喜欢自找麻烦。 15 | 好吧,既然麻烦来了,就得有人去解决,小A的麻烦就靠你来解决了:) 16 | 17 | 关于输入 18 | 19 | 输入包括多组数据,每组数据一行,包含两个正整数n和m(1 <= n <= 100,1 <= m <= 10),其中n表示楼的高度,m表示你现 20 | 在拥有的鸡蛋个数,这些鸡蛋硬度相同(即它们从同样高的地方掉下来要么都摔碎要么都不碎),并且小于等于n。你可以假 21 | 定硬度为x的鸡蛋从高度小于等于x的地方摔无论如何都不会碎(没摔碎的鸡蛋可以继续使用),而只要从比x高的地方扔必然 22 | 会碎。 23 | 对每组输入数据,你可以假定鸡蛋的硬度在0至n之间,即在n+1层扔鸡蛋一定会碎。 24 | 25 | 关于输出 26 | 27 | 对于每一组输入,输出一个整数,表示使用最优策略在最坏情况下所需要的扔鸡蛋次数。 28 | 29 | 例子输入 30 | 31 | 100 1 32 | 100 2 33 | 34 | 例子输出 35 | 36 | 100 37 | 14 38 | 39 | 提示信息 40 | 41 | 最优策略指在最坏情况下所需要的扔鸡蛋次数最少的策略。 42 | 如果只有一个鸡蛋,你只能从第一层开始扔,在最坏的情况下,鸡蛋的硬度是100,所以需要扔100次。如果采用其他策略,你 43 | 可能无法测出鸡蛋的硬度(比如你第一次在第二层的地方扔,结果碎了,这时你不能确定硬度是0还是1),即在最坏情况下你需要 44 | 扔无限次,所以第一组数据的答案是100。 45 | *****/ 46 | 47 | #include 48 | #include 49 | using namespace std; 50 | 51 | #define MAX_N 200 52 | #define MAX_M 20 53 | #define MAX_INT 0x7fffffff 54 | 55 | /** 56 | 思路:动态规划 57 | 58 | dp[i][j]表示共i层楼j个鸡蛋时最优策略的扔鸡蛋的次数。显然dp[i][1] = i(共i层楼1个鸡蛋最优策略是扔i次), dp[1][i] = 1。 59 | 要计算dp[i][j],可以综合从1楼到i楼都扔一次的结果,在里面取最优即可。假设在k楼扔了一个鸡蛋,会出现两种情况: 60 | 1. 若鸡蛋碎了,那么就需要在更低的楼层(1到k-1层)继续测试,扔鸡蛋的次数就是dp[k-1][j-1] + 1; 61 | 2. 若鸡蛋没碎,那么就需要在更高的楼层(k+1到i层)继续测试,扔鸡蛋的次数就是dp[i-k][j] + 1。 62 | 对于每一个k来说,最坏情况是上面的二者中扔鸡蛋次数较多的;对于所有k来说,最优解应该是扔鸡蛋的次数最少的。 63 | 因此dp[i][j] = min_k(max(dp[k-1][j-1] + 1, dp[i-k][j] + 1))。 64 | **/ 65 | 66 | int dp[MAX_N][MAX_M] = {0}; 67 | int cur_n = 0, cur_m = 0; 68 | 69 | int main() 70 | { 71 | int n = 0, m = 0; 72 | for (int i = 1; i < MAX_N; i++) 73 | dp[i][1] = i; 74 | for (int i = 1; i < MAX_M; i++) 75 | dp[1][i] = 1; 76 | for (int i = 2; i < MAX_N; i++) 77 | for (int j = 2; j < MAX_M; j++) 78 | dp[i][j] = MAX_INT; 79 | for (int i = 2; i < MAX_N; i++) 80 | for (int j = 2; j < MAX_M; j++) 81 | for (int k = 1; k <= i; k++) 82 | dp[i][j] = min(dp[i][j], 1 + max(dp[k - 1][j - 1], dp[i - k][j])); 83 | while (cin >> n >> m) 84 | cout << dp[n][m] << endl; 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /2021年期末考试题/装载问题.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 有一批共 n 个集装箱要装上 2 艘载重量分别为 c1和 c2的轮船,其中集装箱 i 的重量为 wi, 5 | 且装载问题要求确定,是否有一个合理的装在方案可将这 n 个集装箱装上这 2 艘轮船。如果有, 6 | 找出最优装载方案。 7 | 8 | 关于输入 9 | 10 | 输入要输入 11 | 1、集装箱数量 类型整型 12 | 2、集装箱重量数组 类型整型数组 13 | 3、两艘轮船的载重量 类型整型数组 14 | 输入格式如: 15 | 5 16 | 67 34 2 69 24 17 | 78 158 18 | 19 | 关于输出 20 | 21 | 如果能装载的话输出格式如下: 22 | ok,can load it 23 | a way is: 24 | the first trip load:2 69 25 | the second trip load:67 34 24 26 | 如果不能装载的话输出如下: 27 | can't find a way to Loading 28 | 29 | 例子输入 30 | 31 | 5 32 | 67 34 2 69 24 33 | 78 158 34 | 35 | 例子输出 36 | 37 | ok,can load it 38 | a way is: 39 | the first trip load:2 69 40 | the second trip load:67 34 24 41 | 42 | 提示信息 43 | 44 | 因为算法的复杂度为 O(2^n),所以建议在测试时不要用 n 太大的数据。 45 | 最优装载问题采用算法:尽量将第一艘轮船装满,然后将剩余的集装箱装到第二艘轮船上。 46 | *****/ 47 | 48 | #include 49 | #include 50 | using namespace std; 51 | 52 | #define MAX_N 100000 53 | 54 | int w[MAX_N] = {0}; 55 | bool visit[MAX_N] = {false}; 56 | int n = 0; 57 | 58 | bool best[MAX_N] = {0}; 59 | int best_left = 0; 60 | 61 | void dfs(int depth, int left) 62 | { 63 | if (left < 0) 64 | return; 65 | if (depth >= n) 66 | { 67 | if (left < best_left) 68 | { 69 | for (int i = 0; i < n; i++) 70 | best[i] = visit[i]; 71 | best_left = left; 72 | } 73 | return; 74 | } 75 | dfs(depth + 1, left); // Do not load w[depth] 76 | visit[depth] = true; 77 | dfs(depth + 1, left - w[depth]); // Load w[depth] 78 | visit[depth] = false; 79 | } 80 | 81 | int main() 82 | { 83 | int a = 0, b = 0; 84 | bool flag = true; 85 | cin >> n; 86 | for (int i = 0; i < n; i++) 87 | { 88 | cin >> w[i]; 89 | best_left += w[i]; 90 | } 91 | cin >> a >> b; 92 | dfs(0, a); 93 | for (int i = 0; i < n; i++) 94 | if (!best[i]) 95 | b -= w[i]; 96 | if (b < 0) 97 | cout << "can't find a way to Loading" << endl; 98 | else 99 | { 100 | cout << "ok,can load it\na way is:\nthe first trip load:"; 101 | for (int i = 0; i < n; i++) 102 | if (best[i]) 103 | { 104 | if (flag) 105 | flag = false; 106 | else 107 | cout << " "; 108 | cout << w[i]; 109 | } 110 | cout << "\nthe second trip load:"; 111 | flag = true; 112 | for (int i = 0; i < n; i++) 113 | if (!best[i]) 114 | { 115 | if (flag) 116 | flag = false; 117 | else 118 | cout << " "; 119 | cout << w[i]; 120 | } 121 | cout << endl; 122 | } 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /第三阶段编程练习5/矩阵取数游戏.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n行*m列的矩阵,矩阵中的每个元素aij均为非负整数。游戏规则如下: 5 | 1. 每次取数时须从每行各取走一个元素,共n个。m次后取完矩阵所有的元素; 6 | 2. 每次取走的各个元素只能是该元素所在行的行首或行尾; 7 | 3. 每次取数都有一个得分值,为每行取数的得分之和;每行取数的得分 = 被取走的元素值*i,其中i表示第i次取数(从1开始编号); 8 | 4. 游戏结束总得分为m次取数得分之和。 9 | 帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。 10 | 11 | 关于输入 12 | 13 | 包括n+1行; 14 | 第一行为两个用空格隔开的整数n和m。 15 | 第2~n+1行为n*m矩阵,其中每行有m个用单个空格隔开 16 | l<=n,m<=80,1<=aij<=1000 17 | 18 | 关于输出 19 | 20 | 仅包含1行,为一个整数,即输入矩阵取数后的最大的分。 21 | 22 | 例子输入 23 | 24 | 2 3 25 | 1 2 3 26 | 3 4 2 27 | 28 | 例子输出 29 | 30 | 34 31 | *****/ 32 | 33 | #include 34 | #include 35 | #include 36 | using namespace std; 37 | 38 | #define MAX_N 100 39 | 40 | /** 41 | 思路:动态规划 42 | 43 | 首先,各行都是独立的,因此可以每一行分开计算,最后的结果加起来即可。 44 | 45 | 对某一行row来说,用dp[i][j](i <= j)表示在[i,j]这个片段进行取数的最大得分。 46 | 显然dp[i][i] = row[i]。 47 | 考虑如何计算dp[i][j],只会出现两种情况: 48 | 1. 先在[i, j]段的左侧(i)取数,那么得分为dp[i+1][j] + sum(row[i+1], row[i+2], ..., row[j]) + row[i] 49 | 2. 先在[i, j]段的右侧(j)取数,那么得分为dp[i][j-1] + sum(row[i], row[i+1], ..., row[j-1]) + row[j] 50 | 因此,当dp[i+1][j]和dp[i][j-1]已知的情况下,dp[i][j]取上述得分的最大值即可。 51 | 我们可以先初始化对角线(dp[i][i]),然后向dp矩阵的右上角计算即可,最终dp[0][length(row) - 1]便是答案。 52 | 53 | 可以使用前缀和sum数组来加速区间求和,sum[i]表示从row[0]一直到row[i-1]的和。那么就可以直接用sum[j+1] - sum[i]来计算某段的和 54 | 55 | 一个例子如下: 56 | 假设row为: 3 4 2 57 | 那么sum为: 3 7 9 58 | dp数组为: 3 -11-> 11 -20-> 20 59 | ^ ^ 60 | | | 61 | 10 19 62 | | | 63 | 0 4 -10-> 10 64 | ^ 65 | | 66 | 8 67 | | 68 | 0 0 2 69 | 整个dp数组的传播计算过程也如上所示。 70 | **/ 71 | 72 | int row[MAX_N] = {0}; 73 | int sum[MAX_N] = {0}; 74 | int dp[MAX_N][MAX_N] = {0}; 75 | int n = 0; 76 | 77 | int main() 78 | { 79 | int n_row = 0, ans = 0; 80 | int r = 0, c = 0; 81 | cin >> n_row >> n; 82 | while (n_row--) 83 | { 84 | memset(dp, 0x00, sizeof(dp)); 85 | for (int i = 0; i < n; i++) 86 | { 87 | cin >> row[i]; 88 | dp[i][i] = row[i]; 89 | sum[i + 1] = sum[i] + row[i]; 90 | } 91 | for (int i = 1; i < n; i++) 92 | for (int j = 0; j < n; j++) 93 | { 94 | r = j - i, c = j; 95 | if (r < 0) 96 | continue; 97 | dp[r][c] = max(dp[r + 1][c] + sum[c + 1] - sum[r + 1] + row[r], 98 | dp[r][c - 1] + sum[c] - sum[r] + row[c]); 99 | cout << r << " " << c << " " << dp[r][c] << endl; // Debug 100 | } 101 | ans += dp[0][n - 1]; 102 | } 103 | cout << ans << endl; 104 | return 0; 105 | } 106 | -------------------------------------------------------------------------------- /第四阶段编程练习2/矩阵乘方和.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 给出一个n*n的矩阵A和正整数k,请求出S=A+A^2+A^3+A^4+...+A^k的值.mat^x表示x个A相乘的结果. 5 | 6 | 关于输入 7 | 8 | 输入包含一组数据. 9 | 第一行是三个正整数n k m, (n<=30,k<=1000000000,m<=10000). 10 | 接下来n行,每行n个数,表示这个矩阵. 11 | 12 | 关于输出 13 | 14 | 输出矩阵S对m取模后的值(即:每个元素对 m 取余),包括n行,每行n个数 15 | 16 | 例子输入 17 | 18 | 2 2 4 19 | 0 1 20 | 1 1 21 | 22 | 例子输出 23 | 24 | 1 2 25 | 2 3 26 | *****/ 27 | 28 | #include 29 | #include 30 | using namespace std; 31 | 32 | /** 33 | 思路 34 | 35 | 首先介绍快速幂,即如何快速求取A^k。 36 | 显然最直接的方法就是循环k次,但这样时间复杂度较高,有更优的方法。 37 | 我们可以发现k是可以分解成二进制编码的,即: 38 | 39 | k = sum_i(2^i), where k's i-th binary code is 1 40 | 41 | 那么显然就有: 42 | 43 | A^k = A^(sum_i(2^i)) = mul_i(A^(2^i)), where k's i-th binary code is 1 44 | 45 | 因此,我们可以用O(log(k))的复杂度而非O(k)来求取A^k。可以参考下面的exp函数 46 | 47 | 48 | 有了快速幂后,我们考虑如何求取A^k的和。 49 | 同样的,最直接的办法就是逐个求取A^k,然后再加起来,但这样的复杂度也很高。 50 | 我们可以构造下面的分块矩阵 51 | 52 | | S(k-1) A^k | 53 | | 0 0 | 54 | 55 | 和 56 | 57 | | I 0 | 58 | | I A | 59 | 60 | 其中,S(k-1) = A + A^2 + ... + A^(k-1)。那么可以发现递推关系 61 | 62 | | S(k-1) A^k | x | I 0 | = | S(k) A^(k+1) | 63 | | 0 0 | | I A | | 0 0 | 64 | 65 | 把上面的递推关系展开,可以得到 66 | 67 | | S(k) A^(k+1) | = | S(0) A | x | I 0 |^k = SA(0) x I0IA^k 68 | | 0 0 | | 0 0 | | I A | 69 | 70 | 使用快速幂求取I0IA^k,然后与SA(0)相乘即可。 71 | 需要注意,在所有计算过程中都需要取模。 72 | **/ 73 | 74 | #define MAX_N 40 75 | 76 | struct Matrix 77 | { 78 | int mat[MAX_N * 2][MAX_N * 2]; 79 | }; 80 | int n = 0, k = 0, m = 0; 81 | 82 | Matrix mul(Matrix &a, Matrix &b) 83 | { 84 | Matrix ret; 85 | for(int i = 1;i <= n; i++) 86 | for(int j = 1;j <= n; j++) 87 | { 88 | ret.mat[i][j]=0; 89 | for(int k = 1; k <= n; k++) 90 | { 91 | ret.mat[i][j] += (a.mat[i][k] * b.mat[k][j]) % m; 92 | ret.mat[i][j] %= m; 93 | } 94 | } 95 | return ret; 96 | } 97 | 98 | /** 快速幂 **/ 99 | Matrix exp(Matrix &a, int x) 100 | { 101 | Matrix ret; 102 | for(int i = 1; i <= n; i++) 103 | for(int j = 1; j <= n; j++) 104 | ret.mat[i][j] = (i == j ? 1 : 0); 105 | for(; x ; x >>= 1) 106 | { 107 | if(x & 1) 108 | ret = mul(ret, a); 109 | a = mul(a, a); 110 | } 111 | return ret; 112 | } 113 | 114 | int main() 115 | { 116 | Matrix a, b; 117 | memset(a.mat, 0, sizeof(a.mat)); 118 | memset(b.mat, 0, sizeof(b.mat)); 119 | cin >> n >> k >> m; 120 | 121 | /** 构造SA(0)和I0IA **/ 122 | for(int i = 1; i <= n; i++) 123 | for(int j = 1; j <= n; j++) 124 | { 125 | cin >> a.mat[i][j + n]; 126 | b.mat[i + n][j + n] = a.mat[i][j + n]; 127 | } 128 | for(int i = 1;i <= n; i++) 129 | { 130 | b.mat[i][i] = 1; 131 | b.mat[i+n][i] = 1; 132 | } 133 | n = n * 2; 134 | 135 | b = exp(b, k); // 快速幂 136 | a = mul(a, b); // 相乘 137 | for(int i = 1;i + i <= n; i++) // 答案在a的左上角分块矩阵中 138 | { 139 | for(int j = 1;j + j <= n; j++) 140 | cout << a.mat[i][j] << " "; 141 | cout << endl; 142 | } 143 | return 0; 144 | } 145 | -------------------------------------------------------------------------------- /第三阶段编程练习4/左手定则.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 玩过RPG(尤其是国产RPG)的童鞋都应该对迷宫这种神棍的设定深恶痛绝,尤其是当你转了半小时之后发现回到 5 | 了原地,这种感觉真是无比的痛苦。。。万一游戏还中途崩溃了那真是连掀桌子、砸键盘、摔鼠标的心都有了…… 6 | 经过无数次的TRIAL AND ERROR之后,玩家终于下定决心认定迷宫存在的意义就是延长游戏时间,SO,他决定借 7 | 鉴著名的左手定则(就是在每一个路口,我们都选择最左边的方向,左转的优先级最高,其次为向前,最后为右 8 | 转,如果实在走进了一个死胡同,那就连续右转两次,回头向后走。稍微研究一下这种走迷宫的方法,我们就发 9 | 现在这个过程中,事实上我们的左手可以始终放在墙上。)对迷宫进行探索。 10 | 但是呢,左手定则并不能保证遍历到迷宫中的每一个点。悲剧的是,某项重要的通关道具被放在了这个迷宫中…… 11 | 幸运的是,游戏迷宫的地图可以绘制出来,现在请求你的帮助。对于一个给定的地图,他想知道是不是能够通过 12 | 左手定则取得这件道具。 13 | 14 | 关于输入 15 | 16 | 多组数据。 17 | 对于每组数据,第一行有两个整数N,M代表接下来有n行字符串,每行m个字符,其中0 68 | #include 69 | using namespace std; 70 | 71 | #define MAX_N 210 72 | #define ND 4 73 | #define NCHAR 26 74 | 75 | bool v[MAX_N][MAX_N][ND]; // visit数组 76 | int d[ND][2] = { // 方向 77 | {-1, 0}, {0, 1}, {1, 0}, {0, -1} // 北,东,南,西 78 | }; 79 | char maze[MAX_N][MAX_N]; // 迷宫 80 | int n = 0, m = 0; 81 | 82 | 83 | /** 按左手定则向下一个位置行走 **/ 84 | void trans(int &x, int &y, int &dir, int dir_to) // 通过引用直接修改x,y和dir 85 | { 86 | dir = (dir + dir_to + ND) % ND; 87 | x += d[dir][0]; 88 | y += d[dir][1]; 89 | } 90 | 91 | bool dfs(int x, int y, int dir) 92 | { 93 | if(maze[x][y] == 'T') // 走到目的地 94 | return true; // 返回true 95 | for(int i = -1; i < 3; i++) // -1左,0前,1右,2后 96 | { 97 | int dx = x,dy = y, d = dir; 98 | trans(dx, dy, d, i); // 得到下一位置和方向 99 | if(v[dx][dy][d]) // 若已经走过 100 | return false; // 则说明进入了循环,返回false 101 | if(maze[dx][dy] != '#' && !v[dx][dy][d]) // 走到下一位置 102 | { 103 | v[dx][dy][d] = true; 104 | return dfs(dx, dy, d); // 递归调用 105 | } 106 | } 107 | return false; 108 | } 109 | 110 | int main() 111 | { 112 | int ss[NCHAR]; // 字符到方向的转换 113 | int sx = 0, sy = 0; // 起始位置 114 | char dir = '\0'; 115 | ss['N' - 'A'] = 0; 116 | ss['E' - 'A'] = 1; 117 | ss['S' - 'A'] = 2; 118 | ss['W' - 'A'] = 3; 119 | while(cin >> n >> m) 120 | { 121 | for(int i = 0; i < n; i++) 122 | for(int j = 0; j < m; j++) 123 | { 124 | cin >> maze[i][j]; 125 | if(maze[i][j] == 'S') 126 | { 127 | sx = i; 128 | sy = j; 129 | } 130 | } 131 | cin >> dir; 132 | memset(v, 0x00, sizeof(v)); 133 | if(dfs(sx, sy, ss[dir - 'A'])) 134 | cout << "YES" < 66 | #include 67 | using namespace std; 68 | 69 | #define MAX_N 5000 70 | #define MAX_LEN 10 71 | 72 | int r2n[MAX_N] = {0}; 73 | char n2r[MAX_N] = "\0"; 74 | 75 | void init() 76 | { 77 | memset(n2r, 0x00, sizeof(n2r)); 78 | n2r[1] = 'I'; 79 | n2r[5] = 'V'; 80 | n2r[10] = 'X'; 81 | n2r[50] = 'L'; 82 | n2r[100] = 'C'; 83 | n2r[500] = 'D'; 84 | n2r[1000] = 'M'; 85 | memset(r2n, 0x00, sizeof(r2n)); 86 | r2n['I'] = 1; 87 | r2n['V'] = 5; 88 | r2n['X'] = 10; 89 | r2n['L'] = 50; 90 | r2n['C'] = 100; 91 | r2n['D'] = 500; 92 | r2n['M'] = 1000; 93 | } 94 | 95 | int roman2num(char* str) 96 | { 97 | int ret = 0; 98 | for (int i = 0; str[i] != '\0'; i++) 99 | if (str[i + 1] != '\0' && r2n[str[i]] < r2n[str[i + 1]]) 100 | ret -= r2n[str[i]]; 101 | else 102 | ret += r2n[str[i]]; 103 | return ret; 104 | } 105 | 106 | void num2roman(int n, char* ret) 107 | { 108 | int base = 1000, idx = 0, c = 0; 109 | while (base) 110 | { 111 | c = n / base; 112 | switch(c) 113 | { 114 | case 9: 115 | ret[idx++] = n2r[base]; 116 | ret[idx++] = n2r[base * 10]; 117 | break; 118 | case 4: 119 | ret[idx++] = n2r[base]; 120 | ret[idx++] = n2r[base * 5]; 121 | break; 122 | default: 123 | if (c >= 5) 124 | { 125 | ret[idx++] = n2r[base * 5]; 126 | c -= 5; 127 | } 128 | for (int i = 0; i < c; i++) 129 | ret[idx++] = n2r[base]; 130 | break; 131 | } 132 | n %= base; 133 | base /= 10; 134 | } 135 | } 136 | 137 | int main() 138 | { 139 | char s[MAX_LEN] = "\0"; 140 | int n = 0; 141 | init(); 142 | while (cin >> s) 143 | { 144 | if (s[0] >= '0' && s[0] <= '9') 145 | { 146 | sscanf(s, "%d", &n); 147 | memset(s, 0x00, sizeof(s)); 148 | num2roman(n, s); 149 | cout << s << endl; 150 | } 151 | else 152 | cout << roman2num(s) << endl; 153 | } 154 | return 0; 155 | } 156 | -------------------------------------------------------------------------------- /2021年期末考试题/拨钟问题.cpp: -------------------------------------------------------------------------------- 1 | /***** 2 | 题目描述 3 | 4 | 有9个时钟,排成一个3*3的矩阵。 5 | 6 | 现在需要用最少的移动,将9个时钟的指针都拨到12点的位置。共允许有9种不同的移动。 7 | 如右表所示,每个移动会将若干个时钟的指针沿顺时针方向拨动90度。 8 | 移动 影响的时钟 9 | 1 ABDE 10 | 2 ABC 11 | 3 BCEF 12 | 4 ADG 13 | 5 BDEFH 14 | 6 CFI 15 | 7 DEGH 16 | 8 GHI 17 | 9 EFHI 18 | 19 | 关于输入 20 | 21 | 从标准输入设备读入9个整数,表示各时钟指针的起始位置。0=12点、1=3点、2=6点、 22 | 3=9点。 23 | 24 | 关于输出 25 | 26 | 输出一个最短的移动序列,使得9个时钟的指针都指向12点。按照移动的序号大小, 27 | 输出结果。 28 | 29 | 例子输入 30 | 31 | 3 3 0 32 | 2 2 2 33 | 2 1 2 34 | 35 | 例子输出 36 | 37 | 4 5 8 9 38 | *****/ 39 | 40 | #include 41 | using namespace std; 42 | 43 | #define N_CLOCK 9 44 | #define MAX_STATE 0xfffff // more than 18 ones 45 | #define N_OP 9 46 | #define MAX_OP_LEN 10 47 | 48 | int visit[MAX_STATE] = {0}; 49 | int q[MAX_STATE] = {0}, q_back = 0, q_front = 0; // Queue 50 | 51 | const char op[N_OP + 1][MAX_OP_LEN] = // Operation 52 | { 53 | "", "ABDE", "ABC", "BCEF", "ADG", "BDEFH", // 1-5 54 | "CFI", "DEGH", "GHI", "EFHI" // 6-9 55 | }; 56 | 57 | /** Check if the queue is empty **/ 58 | bool q_empty() 59 | { 60 | return q_back == q_front; 61 | } 62 | 63 | /** Push item into the queue **/ 64 | void q_push(int enc) 65 | { 66 | q[q_back++] = enc; 67 | q_back %= MAX_STATE; 68 | } 69 | 70 | /** Pop item from the queue **/ 71 | int q_pop() 72 | { 73 | int ret = q[q_front++]; 74 | q_front %= MAX_STATE; 75 | return ret; 76 | } 77 | 78 | /** Update a single clock **/ 79 | int update_clock(int enc, char id, int clock_wise) 80 | { 81 | int i = (id - 'A') * 2; 82 | return (((((enc >> i) & 3) + clock_wise) & 3) << i) | (~(3 << i) & enc); 83 | } 84 | 85 | /** Update multiple clocks according to the operation **/ 86 | int update(int enc, int op_idx, int clock_wise) 87 | { 88 | for (int i = 0; op[op_idx][i] != '\0'; i++) 89 | enc = update_clock(enc, op[op_idx][i], clock_wise); 90 | return enc; 91 | } 92 | 93 | /** Bit encoding of the clocks **/ 94 | int encode() 95 | { 96 | int n = 0, enc = 0; 97 | for (int i = 0; i < N_CLOCK; i++) 98 | { 99 | cin >> n; 100 | enc = enc + (n << (i * 2)); 101 | } 102 | return enc; 103 | } 104 | 105 | void decode(int enc) 106 | { 107 | for (int i = 0; i < N_CLOCK; i++) 108 | cout << (char)('A' + i) << " "; 109 | cout << endl; 110 | for (int i = N_CLOCK - 1; i >= 0; i--) 111 | { 112 | cout << (enc & 3) << " "; 113 | enc = (enc >> 2); 114 | } 115 | cout << endl; 116 | } 117 | 118 | /** Print the operation sequence **/ 119 | void output_op(int enc, int init_enc) 120 | { 121 | int op_idx = visit[enc]; 122 | enc = update(enc, op_idx, -1); // Reverse the operation to recover the previous encoding 123 | if (enc == init_enc) 124 | { 125 | cout << op_idx; 126 | return; 127 | } 128 | output_op(enc, init_enc); 129 | cout << " " << op_idx; 130 | } 131 | 132 | int main() 133 | { 134 | int init_enc = encode(), enc = 0, tmp_enc = 0; 135 | q_push(init_enc); 136 | visit[init_enc] = -1; 137 | while(!q_empty()) 138 | { 139 | enc = q_pop(); 140 | for (int i = 1; i <= N_OP; i++) 141 | { 142 | tmp_enc = update(enc, i, 1); 143 | if (visit[tmp_enc]) 144 | continue; 145 | visit[tmp_enc] = i; // Recording the last operation in visit 146 | if (!tmp_enc) 147 | { 148 | output_op(tmp_enc, init_enc); 149 | cout << endl; 150 | return 0; 151 | } 152 | q_push(tmp_enc); 153 | } 154 | } 155 | return 0; 156 | } 157 | --------------------------------------------------------------------------------