高级模拟算法例题
- 一、P5661 公交换乘
- 1. 审题
- 2. 思路
- 3. 参考答案
- 二、P1003 铺地毯
- 1. 审题
- 2. 参考答案
- 三、P1071 潜伏者
- 1. 审题
- 2. 思路
- 3. 参考答案
一、P5661 公交换乘
1. 审题
2. 思路
总花费中,地铁是必须花费的,公交车可能不花钱(坐地铁后有赠票),但是与时间和价格有一定关系。
我们来分析一下输出的 36 36 36 是如何得出的。
第一行: a n s + 10 ans+10 ans+10
第二行:不用花钱
第三行: a n s + 12 ans+12 ans+12
第四行: a n s + 3 ans+3 ans+3
第五行: a n s + 5 ans+5 ans+5
第六行: a n s + 6 ans+6 ans+6
3. 参考答案
#include <iostream>
using namespace std;int n, way, price, t;
int pos = 1, ans;struct Node
{int freeP;int endT;bool used;
}a[100005];int main()
{// 输入数据cin >> n;while (n--){cin >> way >> price >> t;if (way == 0){ans += price;a[pos].freeP = price;a[pos].endT = t + 45;a[pos].used = false;pos++;}else{while (a[l].endT < t && l < pos-1) // 排除掉过期的赠票{l++;}bool flag = false;for (int i = l; i <= pos-1; i++) // 遍历赠票{if (price <= a[i].freeP && t <= a[i].endT && a[i].used == false) // 价格、时间、是否被用过{a[i].used = true;flag = true;break;}}if (!flag){ans += price;}}}cout << ans;return 0;
}
二、P1003 铺地毯
1. 审题
题目描述
为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有 n n n 张地毯,编号从 1 1 1 到 n n n。现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。注意:在矩形地毯边界和四个顶点上的点也算被地毯覆盖。
输入描述
输入文件名
carpet.in
输入 n + 2 n+2 n+2 行。第一行,一个整数 n n n,表示总共有 n n n 张地毯。
接下来的 n n n 行中,第 i + 1 i+1 i+1 行表示编号 i i i 的地毯的信息,包含四个整数 a a a, b b b, g g g, k k k,每两个整数之间用一个空格隔开,分别表示铺设地毯的左下角的坐标( a a a, b b b)以及地毯在 x x x 轴和 y y y 轴方向的长度。
第 n + 2 n+2 n+2 行包含两个整数 x x x 和 y y y,表示所求的地面的点的坐标( x x x, y y y)。
输出描述
输出文件名
carpet.out
输出共 1 1 1 行,一个整数,表示所求的地毯的编号;若此处没有被地毯覆盖则输出 − 1 -1 −1。
样例1
输入
3 1 0 2 3 0 2 3 3 2 1 3 3 2 2
输出
3
提示
对于 100 % 100\% 100% 的数据, 0 ≤ n ≤ 1 0 4 0\le n\le 10^4 0≤n≤104, 0 ≤ a , b , g , k ≤ 1 0 5 0\le a,b,g,k \le 10^5 0≤a,b,g,k≤105。
2. 参考答案
#include <iostream>
#include <cstdio>
using namespace std;int n;
int tx, ty;
int point[10005][5];int main()
{freopen("carpet.in", "r", stdin);freopen("carpet.out", "w", stdout);// 输入数据cin >> n;for(int i = 1; i <= n; i++){cin >> point[i][0] >> point[i][1]>>point[i][2] >> point[i][3];point[i][2] += point[i][0];point[i][3] += point[i][1];}cin >> tx >> ty;// 模拟bool flag = false;for (int i = n; i >= 1; i--){if (tx >= point[i][0] && tx <= point[i][2] && ty >= point[i][1] && ty <= point[i][3]){flag = true;cout << i << endl;break;}}if (flag == false){cout << -1 << endl;}fclose(stdin);fclose(stdout);return 0;
}
三、P1071 潜伏者
1. 审题
题目描述
R R R 国和 S S S 国正陷入战火之中,双方都互派间谍,潜入对方内部,伺机行动。历尽艰险后,潜伏于 S S S 国的 R R R 国间谍小 C C C 终于摸清了 S S S 国军用密码的编码规则:
- S S S 国军方内部欲发送的原信息经过加密后在网络上发送,原信息的内容与加密后所得的内容均由大写字母
'A'
− - −'Z'
构成(无空格等其他字符)。- S S S 国对于每个字母规定了对应的"密字"。加密的过程就是将原信息中的所有字母替换为其对应的"密字"。
- 每个字母只对应一个唯一的"密码",不同的字母对应不同的“密字”。“密字”可以和原字母相同。
例如,若规定
'A'
的密字为'A'
,'B'
的密字为'C'
(其他字母及密字略),则原信息"ABA"
被加密为"ACA"
。
现在,小 C C C 通过内线掌握了 S S S 国网络上发送的一条加密信息及其对应的原信息。小 C C C 希望能通过这条信息,破译 S S S 国的军用密码。小 C C C 的破译过程是这样的:扫描原信息,对于原信息中的字母 x x x(代表任一大写字母),找到其在加密信息中的对应大写字母y,并认为在密码里 y y y 是 x x x 的密字。如此进行下去直到停止于如下的某个状态:
- 所有信息扫描完毕,
'A'
− - −'Z'
所有 26 26 26 个字母在原信息中均出现过并获得了相应的“密字”。- 所有信息扫描完毕,但发现存在某个(或某些)字母在原信息中没有出现。
- 扫描中发现掌握的信息里有明显的自相矛盾或错误(违反 S 国密码的编码规则)。例如某条信息
"XYZ"
被翻译为"ABA"
就违反了“不同字母对应不同密字”的规则。
在小 C C C 忙得头昏脑涨之际, R R R 国司令部又发来电报,要求他翻译另外一条从 S S S 国刚刚截取到的加密信息。现在请你帮助小 C C C:通过内线掌握的信息,尝试破译密码。然后利用破译的密码,翻译电报中的加密信息。
输入格式
共 3 3 3 行,每行为一个长度在 1 1 1 到 100 100 100 之间的字符串。
第 1 1 1 行为小 C C C 掌握的一条加密信息。
第 2 2 2 行为第 1 1 1 行的加密信息所对应的原信息。
第 3 3 3 行为 R R R 国司令部要求小 C C C 翻译的加密信息。
输入数据保证所有字符串仅由大写字母'A'
− - −'Z'
构成,且第 1 1 1 行长度与第 2 2 2 行相等。
输出格式
共 1 1 1 行。
若破译密码停止时出现 2 , 3 2,3 2,3 两种情况,请你输出Failed
(注意首字母大写,其它小写)。
否则请输出利用密码翻译电报中加密信息后得到的原信息。
样例1
输入
AA AB EOWIE
输出
Failed
提示
样例 1 1 1 中原信息中的字母
'AA'
和'BB'
对应相同的密字,输出Failed
。
2. 思路
我们可以直接用一个一维数组(桶),来存储密码(下标)和对应的原码(数据)。
3. 参考答案
#include <iostream>
#include <string>
using namespace std;string y, m, ans; // y: 原码 m: 密码 ans: 密码答案
int cnt = 0; // 记录出现次数
int bm[130]; // bm[]: 编码存储
bool yused[130]; // yused[]: 记录原下标是否被使用过int main()
{cin >> m >> y >> ans;// 特例int len = m.length();if (len < 26) // 密码长度<26直接输出{cout << "Failed";return 0;}// 正常情况for (int i = 0; i <= len-1; i++){if (bm[m[i]] == 0 && yused[y[i]] == false) // 新的{bm[m[i]] = y[i];cnt++;yused[y[i]] = true;}else{if (bm[m[i]] == y[i]){continue;}else // 诱惑的原码{cout << "Failed";return 0;}}}if (cnt < 26){cout << "Failed";return 0;}int len2 = ans.length();for (int i = 0; i <= len2-1; i++){cout << char(bm[ans[i]]);}return 0;
}