HDU 3rd “Vegetable-Birds Cup” Programming Open Contest

来源:互联网 发布:淘宝直通车问题 编辑:程序博客网 时间:2024/05/21 15:00

额话说我java用着用着,就又用回了c++,而且我发现每次遇到大数据量的问题时,用java会莫名的出错

比如http://acm.hdu.edu.cn/discuss/public/post/reply.php?postid=2415&messageid=1&deep=0

如果有高手能解答我这个疑惑,感激不尽,我觉得是大量内存开销引起的,但是又不知道具体出在哪里,没道理啊

翻译成c++就可以,遇到了N次了,这个问题也成了我做这套题的最大发现

话不多说,开始贴我的思路

题目地址http://acm.hdu.edu.cn/search.php?field=problem&key=HDU 3rd “Vegetable-Birds Cup” Programming Open Contest&source=1&searchmode=source

 

A:

题目描述:给定万米跑当前时刻的排名,和当前时刻每个人的位置

判断这种局面是否正确

分析:其实问题的核心都在套圈上,我们先对选手按排名排序

从前面往后面分析,建立一个以第一个人为原点的相对位置坐标系

然后根据前后两名的位置,来确定后一个的相对位置,然后判断是否溢出即可

 

B:

我个人认为这题是这套题中最值得做的((*^__^*) 嘻嘻……)

题目描述:有n种积木初始将积木放在X轴每个积木有起始和终止坐标S[i],E[i],高均为1 

 最终高度不能超过H,对于积木i能放在积木j上面

当且仅当S[i]>=S[j]&&E[i]<=E[j],求最多能用多少块积木,除了第一层

其他层可以放>=2个的积木 

 

分析:最早我的dp方程是按照坐标来设定的即dp[h][i][j]表示高度为h,在坐标[i,j]之间能容纳的最大

但是我后来很快就意识到这样做回使得若存在重叠的积木,他们是一摸一样的,我无法辨别,没法判断是已用的

还是未用的,还是用了多少,所以很自然的wa了

后来改变了策略,把积木看做是一个个物品,应该是要像背包一样一个个放进去,这样就能很好的解决

上面的那种情况,那么状态的设计呢,这里是费了一点脑子的

这里首先要做一个排序,先按x小到大排,x相等按y大到小(构建拓扑序) 

dp[h][i][j]表示在第h层i号和j号之间最多能容纳多少(注意i为根)

那么怎么转移呢,定义一个新的数组w[h][i]表示在第h层以i为根的最大容量

先枚举h,然后枚举i,然后枚举j,其中的j从i+1开始,且保证j被i容纳

再枚举一个k,这个k是被i容纳的,也就是说在当前这个状态下k是一个起点最靠右的且被i容纳的,这里要细细体会

(注意我刚提到的拓扑序,一个拓扑序的合法子集对应了一个方案哦)

那么我们得到上一层以j为根的状态,将i套在其外面,总的复杂度为h*n*n*n 

其实整个状态转移图是一个满足拓扑关系的图

其实想清楚了代码一点也不多,而且不容易错

 

C:

题目描述:给定一个字符串,求至少添加多少字符

使得添加后的字符串是一个以特定字母循环的长串(循环次数大于等于2)

分析:由于最终要形成循环串,于是左边加字符和右边是等效的

我们全都等效到右边去,接下来就是求循环节长度

为n-next[n-1],然后看n%(n-next[n-1])=r若r为0表示不需要添加

否则添加若干使得其整除即可

 

D:

题目描述:给定一个任务栏,有些任务选中了,有些没有(初始选中状态)

有两类特殊点击(1)全选(2)选择与当前状态相反的任务选项

现在要用最少的点击次数,选中想要的一些任务

分析:显然如果全选要用,只会用一次且要用必定在初始

如果反选要用,也只会用一次,联想下BFS的状态即可

那么一共是四种情况(1)用全选不用反(2)用反不用全(3)都不用(4)都用 取最小即可

 

E:

题目描述:给定n个砝码及其重量,给定m对砝码表示其不能同时用

用k个砝码问能否组成质量v

方法折半,用v1存有矛盾的砝码+若干砝码上限为n/2,v2存无关的砝码

暴力枚举v1的选取状态,剔除掉非法状态,得到砝码的一些组合

用set保存下来,然后再枚举集合v2,利用v和k得到还需要的物品组合

那么就可以利用set很快速的查询了,set中最多会有2^16个组合 

总体复杂度2^16*max(16*16,log(2^16))(涉及到有剪枝效果)

 

F:

题目描述:给定n个点m条边的无向图

给定Q个询问,问两点之间有几条互不相交了路

本质上是判断两个点是否在同一个环内

对于存不存在路径我们可以用幷查集快速的得到结果

对于存在的,那么至少存在一条,现在对图做双联通分量

有一种特殊情况,当前块只有一条边,那么其实是只有一条路

好久不敲双联通了,没想到一次就过了

我实现的代码极限复杂度是O(max(m,n*q))

 

G:

题目描述:给定一个上限数n,求用二分查找的期望查询的次数

我用的是笨办法

我们知道最坏情况的次数为[logn],我们用最笨的办法遍历每个结果

得到该数字的次数,然后根据期望的定义搞即可复杂度nlogn

 

H:

有点烦人的最短路(or BFS)问题,稍后再写

 

I:

水题不解释

原创粉丝点击