2019暑期集训 - Day 10

困 . . .





概述

提高 B 组
4题:T0 , T1 , T2 , T3
155/400 分
69/140 名


T0 洪水

WA 60/100 分

Description

一天, 一个画家在森林里写生,突然爆发了山洪,他需要尽快返回住所中,那里是安
全的。
森林的地图由 \(R\)\(C\) 列组成,空白区域用点 "." 表示,洪水的区域用 "*" 表示,而岩石用 "X" 表示,画家的住所用 "D" 表示,画家用 "S" 表示。
有以下几点需要说明:

  1. 每一分钟画家能向四个方向移动一格(上、下、左、右)
  2. 每一分钟洪水能蔓延到四个方向的相邻格子(空白区域)
  3. 洪水和画家都不能通过岩石区域
  4. 画家不能通过洪水区域(同时也不行,即画家不能移到某个格子,该格子在画家达到的同时被洪水蔓延到了,这也是不允许的)
  5. 洪水蔓不到画家的住所。

给你森林的地图,编写程序输出最少需要花费多长时间才能从开始的位置赶回家中。

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)\) 常数时间,或是用哈希算法、不定长数组来减小空间占用。
最后是对于细节的优化,比如快读、快写、位运算等等能提高一点点效率的小技巧。

posted @ 2019-12-27 16:57  imzzy  阅读(54)  评论(0)    收藏  举报