第一题:
题目大意:
N层楼,K个人,M个箱子在1楼,给出K个人的初始状态(在第几楼,正在向上走还是向下走,向上走的人手里已经有箱子),每次移动一层楼,求把所有箱子(手里拿着的不算在M里)全部搬到顶楼的最少时间。
K≤500000,M≤10^9
解题过程:
1.首先想到可以二分时间t,然后判断在时间t里能否搬完。根据向上走还是向下走分情况讨论每个人在时间t里最多能搬多少个箱子,然后加起来和剩下的箱子比较。初始得分50分,因为输出答案的时候用了printf("%d",ans),而ans是long long类型的。这个方法时间比较慢,最慢的点要0.6s+;
2.优化:对于任何一个人,经过时间2*(N-1) 后,他的状态不变,但是已经把1楼的一个箱子拿上去了。所以每次经过2*(N-1)的时间,底下的箱子就会减少k个;所以可以先把箱子M mod k,任何加上相应的时间。加上这个优化,时间最慢的点只要0.07s左右。
3.标准解法:首先用一下优化2.假设地上还有X个箱子,那么只要找到第X个到底层的人,他到顶层的时间就是总时间。就转换成找第k大问题了。
第二题:
题目大意:
N头奶牛围成一个圈,给出两两之间的距离,求出最远的两头奶牛的距离。奶牛A 到B 的距离为A 顺时针走和逆时针走,到达B的较短路程。
2≤N≤100000
解题过程:
1.先把环断成链,然后枚举起点,二分终点来求从奶牛A出发的最远距离(找到一个B,使得AB的距离尽可能接近总距离sum的一半)。初始得分70分,原因是把环断成链的时候数组应没开两倍大。还有如果A和A后面的第一个点之间的距离d就大于sum/2了,那么结果应该是sum-d。
2.更完美的O(n)算法:对于起点A的最远点是B,如果另外起点C在A的右边(顺时针往后数),那么C的最远点在B的右边(顺时针往后数),前面的算法每次都要二分实际上反而浪费了时间。只要用2个指针,一个表示起点,一个表示终点,起点往后移动,终点也会往后移动。这样最多起点终点各走了一圈,复杂度O(2*n);
第三题:
题目大意:n天,m个码头,e条边,求出n天从1号码头到m号码头的费用。 一些码头在某些天会不能通过。每次改变航线要花费k。n<=100,m<=20
解题过程:
1.一开始看到数据范围比较小,感觉会是贪心或者搜索,但是贪心有后向性,搜索没有给力的剪枝肯定又超时。时间不够想不到更好的算法。初始得分0分。
2.标准算法:动态规划+最短路。
状态转移方程:f [i]=min{dist(1,i)*i,f[j]+dist(j+1,i)*(i-j)+k) (1=<j≤i-1)。
f [i]表示前i天的最小运费,dist(x,y)表示从第x天到第y天从起点到终点的最短路(只要把第x天到第y天的崩溃的码头暂时去掉做最短路);
第一种情况:1到j天都走一条路。
第二种情况:j+l到i天走一条路(这条路记为路径1)。这个时候,不管前j天走的路径。