2019暑期集训 - Day 10
困 . . .
概述
提高 B 组
4题:T0 , T1 , T2 , T3
155/400 分
69/140 名
T0 洪水
WA 60/100 分
Description
一天, 一个画家在森林里写生,突然爆发了山洪,他需要尽快返回住所中,那里是安
全的。
森林的地图由 \(R\) 行 \(C\) 列组成,空白区域用点 "." 表示,洪水的区域用 "*" 表示,而岩石用 "X" 表示,画家的住所用 "D" 表示,画家用 "S" 表示。
有以下几点需要说明:
- 每一分钟画家能向四个方向移动一格(上、下、左、右)
- 每一分钟洪水能蔓延到四个方向的相邻格子(空白区域)
- 洪水和画家都不能通过岩石区域
- 画家不能通过洪水区域(同时也不行,即画家不能移到某个格子,该格子在画家达到的同时被洪水蔓延到了,这也是不允许的)
- 洪水蔓不到画家的住所。
给你森林的地图,编写程序输出最少需要花费多长时间才能从开始的位置赶回家中。
Input
输入第一行包含两个整数 \(R\) 和 \(C\ (R,C\leq 50)\) 。
接下来 \(R\) 行每行包含 \(C\) 个字符 ( "."、"*"、"X"、"D" 或 "S" ) 。地图保证只有一个 "D" 和一个 "S" 。
Output
输出画家最快安全到达住所所需的时间,如果画家不可能安全回家则输出 "KAKTUS" 。
Sample Input
输入1:
3 3
D.*
...
.S.
输入2:
3 3
D.*
...
..S
输入3:
3 6
D...*.
.X.X..
....S.
Sample Output
输出1:
3
输出2:
KAKTUS
输出3:
6
Solution
这题我都能错
好简单的暴搜,先广搜一遍洪水到每个位置的时间,然后随便深搜还是广搜查询每个点到家的最小时间(最小时间大于等于之前写的洪水到这个点的时间时,就属于 "KAKTUS" 了),最后输出起点对应的时间就完事了。
T1 邦德I
TLE 55/100 分
Description
每个人都知道詹姆斯邦德,著名的007,但很少有人知道很多任务都不是他亲自完成的,而是由他的堂弟们吉米邦德完成(他有很多堂弟),詹姆斯已经厌倦了把一个个任务分配给一个个吉米,他向你求助。
每个月,詹姆斯都会收到一些任务,根据他以前执行任务的经验,他计算出了每个吉米完成每个任务的成功率,要求每个任务必须分配给不同的人去完成,每个人只能完成一个任务。
请你编写程序,得到所有任务都成功完成的概率的最大值。
Input
输入第一行包含一个整数N,表示吉米邦德的数量以及任务的数量(正好相等, \(1\leq N\leq 20\) )。
接下来 \(N\) 行,每行包含 \(N\) 个 \(0\) 到 \(100\) 之间整数,第 \(i\) 行的第 \(j\) 个数 \(A_{i,j}\) 表示吉米邦德 \(i\) 完成任务 \(j\) 成功的概率为 \(A_{i,j}\%\)
Output
输出所有任务成功完成最大的概率,结果保留 \(6\) 位小数。
Sample Input
输入1:
2
100 100
50 50
输入2:
2
0 50
50 0
输入3:
3
25 60 100
13 0 50
12 70 90
Sample Output
输出1:
50.000000
输出2:
25.000000
输出3:
9.100000
Solution
状态压缩 DP
将任务已完成的状态用二进制的方式表示(\(1\) 为完成,\(0\) 为未完成)
比如在 \(1,2,3,4,5,6\) 六件事中已完成了 \(1,3,4,5\) 四件事,就记为 \((101110)_ 2\) ,完成 \(2,5,6\) 三件事就记作 \((010011)_ 2\)
因为每人只能做一件事,所以不妨设 \(f_i\) 代表前几个人做 \(i\) 代表的状态时,能得到的最大成功率。
比如如果共有六件事,那么 \(f_{19}=f_{(010011)_ 2}\) 代表前 \(3\) 人(因为这个二进制数中有 \(3\) 个 \(1\) ,所以完成了 \(3\) 件事,所以需要 \(3\) 个人),完成 \(2,5,6\) 三件事所能得到的最大成功率。
这样,我们就可以用 \(f\) 递推答案了,比如 \(f_{(010001)_ 2}=\max(f_{(010000)_ 2}\times a_{2,6},f_{(000001)_ 2}\times a_{2,2})\) 其中 \(a_{i,j}\) 代表第 \(i\) 个人做第 \(j\) 件事的成功率。
也就是从上一个可能的状态转移,得到的 \(f_{2^n-1}=f_{(11111\cdots 11)_ 2}\) 即为答案。
T2 餐桌
RE 30/100 分
Description
你家刚买了一套新房,想邀请朋友回来庆祝,所以需要一个很大的举行餐桌,餐桌能容纳的人数等于餐桌的周长,你想买一个能容纳最多人的餐桌,餐桌的边必须跟房间的边平行。
给你的房间的设计,计算最多能邀请的客人数。
Input
第一行包含两个整数 \(R\) 和 \(C\ (1\leq R,C\leq 2000)\) ,表示房子的长和宽。
接下来 \(R\) 行每行 \(S\) 个字符(中间没有空格),"." 表示空白区域,"X" 表示有障碍物,餐桌所占区域必须是空白的。
Output
输出最多能要求的客人数量。
Sample Input
输入1:
2 2
..
..
输入2:
4 4
X.XX
X..X
..X.
..XX
输入3:
3 3
X.X
.X.
X.X
Sample Output
输出1:
7
输出2:
9
输出3:
3
Hint
50% 的数据 \(R,C\leq 400\)
70% 的数据 \(R,C\leq 1000\)
100% 的数据 \(R,C\leq 2000\)
Solution
嘿,还带改数据范围的
从 \(400\) 提到 \(2000\) 意味着 \(O(N^3)\) 的破灭,必须优化一下了
预处理 \(a_{i,j}\) 代表从第 \(i\) 行第 \(j\) 列的位置开始向左多少格都空白;
然后枚举每个位置 \((i,j)\) ,如果是空地就再向下枚举每一行 \(k\) 的第 \(j\) 格,每次存储最小的 \(f_{k,j}\) 至 \(minw\),然后使 \(ans=\max(\ ans,2(\ minw+k-i+1\ )\ )\) 。因为 \(minw\) 是从第 \(i\) 行到第 \(k\) 行,以第 \(j\) 列的位置开始向左空白格数最少的值,所以以 \((i,j)\) 为右上角以 \(k-i+1\) 为高的矩形宽的最大值为 \(minw\) ,周长即为 \((\ minw+k-i+1\ )\times 2\) ,用这个值尝试更新 \(ans\) 中存储的最大周长。
最后输出 \(ans-1\) 即可。
T3 自行车比赛
WA 10/100 分
Description
自行车赛在一个很大的地方举行,有 \(N\) 个镇,用 \(1\) 到 \(N\) 编号,镇与镇之间有 \(M\) 条单行道相连,起点设在镇 \(1\) ,终点设在镇 \(2\) 。
问从起点到终点一共有多少种不同的路线。两条路线只要不使用完全相同的道路就被认为是不同的。
Input
第一行两个整数: \(N\) 和 \(M\ (1\leq N\leq 10000,1\leq M\leq 100000)\) ,表示镇的数量和道路的数量。
接下来 \(M\) 行,每行包含两个不同的整数 \(A\) 和 \(B\),表示有一条从镇 \(A\) 到镇 \(B\) 的单行道。
两个镇之间有可能不止一条路连接。
Output
输出不同路线的数量,如果答案超过 \(9\) 位,只需输出最后 \(9\) 位数字。如果有无穷多的路线,输出 "inf"。
Sample Input
输入1:
6 7
1 3
1 4
3 2
4 2
5 6
6 5
3 4
输入2:
6 8
1 3
1 4
3 2
4 2
5 6
6 5
3 4
4 3
输入3:
31 60
1 3
1 3
3 4
3 4
4 5
4 5
5 6
5 6
6 7
6 7
…
…
…
28 29
28 29
29 30
29 30
30 31
30 31
31 2
31 2
Sample Output
输出1:
3
输出2:
inf
输出3:
073741824
Solution
方法1
虽然我不会
好吧,其实就是先用 Tarjan 算法求环,割掉无用的环,然后再拓扑排序一遍,最后递推答案。
方法2
来自某巨佬的题解,我搬上来再解释解释
其实也很简单,就是先从节点 \(1\) 开始广搜一遍,再反向建图从节点 \(2\) 开始广搜一遍,得到每个点能不能从 \(1\) 走到,和能不能走到 \(2\) 。如果这个点既能从 \(1\) 走到,又能走到 \(2\) ,就说明它可以出现在 \(1\) 至 \(2\) 的路径中,反之则不会,而因为它则不会出现在 \(1\) 至 \(2\) 的路径中,所以它对于从 \(1\) 到 \(2\) 的路径是无意义的,我们就可以从图中删去这一节点。
这样给图剪枝后,我们就能避免以后绕进一个对于从 \(1\) 到 \(2\) 的路径无意义的环中死循环或是 inf 。
最后再一遍广搜求路径数就行了。
优化
O2 O3
停停停,不是那些东西
在做题中,对于各种算法的时间、空间优化常常是必不可少的一部分,有时能很大程度上增加效率。
比如动态规划的题目,我们常常可以使用滚动数组和离散化来减小数组占用的空间,用记忆化搜索来提高时间效率。
对于图论等题目,经常可以剪一部分枝,这会让程序快许多,也能减小错误率。
还有对于一些题目,数据结构的优化是必不可少的,比如使用队列、栈、堆、链表等结构维护数据,常常能将 \(O(N)\) 的检索改善至 \(\log\) 级别,甚至到 \(O(1)\) 常数时间,或是用哈希算法、不定长数组来减小空间占用。
最后是对于细节的优化,比如快读、快写、位运算等等能提高一点点效率的小技巧。

浙公网安备 33010602011771号