usaco 1.1- 4.2总结合集 (2012年寒假)


section 1.1 水模拟。回复回复代码能力。。 section 1.2 complete searchnnnn(枚举搜索)

减少不必要的枚举
transform写的挺搓,矩阵变化应该用struct的才好的。。。
Name That Number 同样是建立两个集合的关系,在保证内存的情况下,显然是写成函数映射用起来更方便啊。。。
1.2切的没有压力。。。


section 1.3 一天内切完,水。。
section 1.4 More Search Techniques 


Packing Rectangle
bt模拟。。一共耗时4+h,写到0:40。。
写这种大模拟题,一定要有严谨规范的思路。
此题主要是要对题中给的5种(4,5种一样)基本模型进行严格定义


1.四个矩形排成一列
2.有三个矩形在一个矩形上边
3.只有两个矩形在一个矩形上边,第四个矩形和他们排成一排
4.高度最小的矩形上有一个矩形,并和剩下的两个矩形排成一排
5.四个矩形两两上下组合,形成两个新矩形,每个新矩形都要高于每个在新矩形中处于下方老矩形
(高表示纵向长度)。


有了定义,那么我们只要枚举出四个矩形的全排列+每个矩形的翻转情况 (4! * 2^4),对每种组合,判断能不能满足这5种基本模型,满足则求enclosing rectangle,更新结果。
这题还有一个发现,就是全局变量容易出问题,可能应为是地址冲突还是什么的,反正值会莫名其妙的改变。看来对于代码量大的程序还是要少用它为好。


The Clocks
刚开始一看要求最短移动步骤,就觉得要用bfs,或ID,因为dfs感觉dfs好写,就用ID
写完只有发现不对,因为枚举量是4^9,应该是每层4枚举四个菜对啊。。我成了枚举九个。。写的好烂,果断擦掉重写,想搜索一定要想清楚枚举法再写啊。。
最后dfs 1Y。。
airprog
水枚举,但犯了2B错误,没考虑有重复的。。。看了看analysis,发现它的快方法和我的一样 ^ ^
milk3 也是水题这种题,本来想以此写完不用改直接A的,但是第一次没看到A要为0的条件,而且倒水那个函数犯2写错了。。涂涂改改。。最后1Y。不过我写的时候用用3D数组保存的状态,其实用2D就好,b,c唯一确定a·
终于做完1.4了。。做的好慢。。


section 1.5
(1) 数塔。。。
(2)prime Palindromes
此题数据范围是5-100000000,,比较大,比较有效的方法之一是构造回文数在做素性判断,我在构造的时候,第一次是枚举后一半0-10000,但这样就出现,本来想产生120021,结果变成了1221。后来改为枚举前一半,翻转数要补前导零就用printf("%*d",len,revn)。很方便。
(3)Superprime Rib 递推打表即可
(4)checker Challenge 经典的N皇后问题,这题N<=13,记录对角线和列的访问情况即可过,当然解决这个问题还有一个更简洁更高效的方法--位运算,这个详见Matrix67的blog


section 2.1
The Castle dfs练习题,但刚开始误解了"the module farthest to the west"的意思
这就话应该是“最西面的单元”,我居然理解成了优先考虑拆西墙。- - bs我。


Ordered Fractions 休闲题,枚举排序。。。但是忘了考虑2/4这种情况,又没1Y。。。- -不过Analysis的方法还是很不错的,发现了if n1/d1 < n1+n2/d1+d2 < n2/d2这一规律,分治解决。


Sorting a Three-Valued Sequence  水,1Y
定义num[i][j]为在排完序后数值为i的位置里在排序前j的个数
则答案为num[1][2]+num[1][3]+ num[3][2] + positive(num[1][2]-num[2][1])
其中#define positive(n) (n < 0 ? 0 : n) 


Healthy Holsteins 水题,IDDFS过掉
Hamming Codes 水题。。


section 2.2
这题要用构成Roman数字的基本元素构成阿拉伯数字,只要把阿拉伯数字按位分解,再对照基本元素转换即可


Subset Sum
刚开始没注意N的范围,就随便dfs了一下,然后就悲剧了。。
但此时我还想能不能剪剪枝过去(被前面的题目养成习惯了。。)
弄了半天,还是不行,只能放弃。。瞄一眼解题报告,dp!!还是经典的dp题。
我才想起来还有dp这么个东东。。。(- -0),那是在很久很久以前。。。
言归正传这题应该属于01背包问题,取或不取
dp[i][j]表示用前j个数组成i的组合数。
显然有dp[i][j] = dp[i-j][j-1] + dp[i][j-1]


Runaround Numbers 虽然是个暴力题,但各种没看清题意。。- -0比如" with unique digits", "end up at a new digit ".....


Party Lamps 这题扎题看很简单,因为每个按钮按两次就等于没按,所以一共就16种状态,原以为半小时内搞定,但谁知被排序卡了一个多小时。。原本用bool []记录状态,因为要保存,要排序,考虑改个数据结构,突然想到c++有bitset,用了一下,发现他居然没有重载比较运算符!,又老老实实改成了char [],原以为大功告成,但又出现了很奇怪的bug,一直我怀疑是code::blocks的问题,后来才发现我少了一个else。。
纠结了半天才搞掉。。代码能力实在太弱。。
看Analysis,发现状态是以6为循环节的,不过这题数据太小,没仔细想。


section 2.3
Longest Prefix 题意:
字符串集合S,字符串C,如果C可通过S中的字符串拼凑成,则成C满足性质H,问C中满足性质H的最长前缀是多少。
正常人一看就知道不能暴。。。我不正常。。不能暴,就dp呗
字符串长度是200000,比较大,应该是一维的。那dp[i]表示什么,苏牛暗示了我一下
dp[i]表示以第i个字符开头的字符串的最长前缀的长度,我恍然大悟(Orz苏牛!),
dp[i] = max(dp[j] + (j-i)) (保证str[i..j-1]是primitive),二分优化后复杂度是
200000*10*lg(200),没有问题。偷懒用stl,写起来很简单
(习惯上dp都是从前晚后推,但这题不行,应为重点是前缀,重点在前面,和后面的没关系,一定要把dp[]放在最影响结果的地方)
(我真的已经不会dp了。。。。T_T)


Cow Pedigrees 题意:
如果二叉树满足每个父节点有且只有两个子节点,则称其满足性质D,求总节点数为n,深度为k的D二叉树个数。
计数问题,首先很自然的看出相邻两层之间存在递推关系,刚开始我尝试用dp[i][j]表示第i层一共j个节点时的状态数,在推方程时发现不行,改为dp[i][j][k]表示
一共i层一共j个节点且第i层节点数为k时的状态数。设定好状态,第i-1层的每个节点都可能成为第i层的父节点,递推方程为dp[i][j][k] = sum(dp[i-1][j-k][h]*C(h,k)),写的时候要注意一些边界细节。
看了一下Analysis的方法,比我的要快


Zero Sum dfs暴力


Money Systems 经典的母函数应用。。太激动没用long long,2Y。。看Analysis发现有更好的方法dp[i]表示组成数值i的方法数,这个状态可来源自dp[i-v[j]] (0<j<=V,v[i]表示第i种硬币的数值。得dp[i] = sum(dp[i-v[j]]) 无论从时间还是空间上都要好于用母函数啊。


Controlling Companies 
这题看完之后第一反应就是Floyd,也没细想,交了之后果然就wa了。然后就改用dfs,就tle,挑了半天也没找出是拿错了。。最后实在没办法,瞥一眼解题报告,发现自己理解错题意了!!题中第三条control条件是说A要想通过C去控制B,是要依靠CB间的直接股份的累加才行,不能是间接股份,而我显然没有注意到这一点。。报告给出的方法也十分简洁明了。对于condition 1,2所确定的关系,可在输入完数据后就确定。而对于condition3,则需要不断重复一下操作来更新:对于公司i,j如果i没控制j,就枚举k去尝试间接更新i,j,如果对于所有的i,j都没有更新,则以后必然也不会有更新了,即更新结束。(Orz leokan...)


2.4
The Tamworth Two 
这题是模拟题,刚开始我考虑到farmer和cows的状态都是一共100*4种,所以是有循环的。只要找到循环周期和共同走过的点的时间差,就可以推算出知否能相遇。但是这样做比较麻烦,会有一些细节。在一想把farmer和cows同时考虑,一共的状态时160000种,很少只要模拟两者移动直至遇到重复状态位置即可(6D数组- -0.。)之后看Analyis他连状态都没记录!160000实在太少直接循环160000即可,大气!!以后分析问题,要多从全局考虑才行,不要陷入追求技巧的陷阱!!!暴力也是一种美。要宏观要大气,以高效解决问题问宗旨。


Overfencing
这题刚开始想用dfs去floodfill,结果tle,还差不出错误。。。无奈看标称,改用bfsfloodfill,设一个虚拟的根节点,入口为第一层,然后像遍历树一样,层次遍历整个迷宫。答案可有树的深度得出。但是由于队列开小了。老是wa,很奇怪。最大节点数应该没所措,没什么会不对呢。。


Cow Tours
被题意纠结了好久。。。。
Floyd算出所有点之间的距离,和传递闭包。求出区域内的最大直径么d1,然后N^2遍历,如果不相连则求出相连后新区域的直径,选出最小的d2,ans = max(d1,d2)
这题刚开始没想清怎么计算加一条边(a,b)链接field A和field B后的直径,后来想到所谓最大距离么,就是A中离a最远的点到B中离b最远的点的距离。


Bessie Come Home
赤裸裸的Floyd最短路。。但是。。第一次没考虑是无向图,第二次没考虑重边。。。。感觉现在太依赖usaco的测试数据了。。。交的太冲动。。。。。要注意!!尽量不看他的数据!!


Fraction to Decimals
交了n次终于过了。。多亏usaco能看错的数据。。- -0
这题时要模拟竖式除法运算,记录余数,余数相同是即说明是循环小数。
wa的原因主要有两个
1.数组没开够,开了3000000才行
2.判断循环小数时,对重复余数的判断的一个细节上没考虑
如105%104 == 1,则1,10,100,都是其产生的余数,而我只判断的1
如果不是usaco能看错的数据,估计很难找出来


section 3.1
Agri-Net 裸最小生成树


Score Inflation 无限背包,记得当初看无限背包的时候,看的迷迷糊糊,而这次我读完题之后,很自然的就想出了的转移方程,看来自己的水平真的提高了。。^ ^
dp是在过程中求得最优解,所以只要我们能清晰的认识到每个状态的所有来源,根据最优子结构的特性,自然不难得出转移方程。
dp[i] 为最大时间是i时的最优结果。方程为dp[i] = max(dp[i],dp[i-time[j]]+score[j])。


Humble Numbers dp
首先看数据量K<=100,N <= 100000,K*N的复杂度是可行的。dp[i] 表示第i个数,而hum number的来源必然可以写成p[j]*hum[k]的形式(最关键的一步),由此
dp[i] = min(dp[i],dp[k[j]]*p[j])。(自己的dp感觉好像又回来了。。。^ ^)


Shaping Regions
给一堆矩形,求从上往下看没被覆盖的面积。
这题属于看解题报告过,- -b,了解了离散化矩形切割这个东西,很不错


usaco 3.2
Factorials
这题一读完我就抱着实验的心态开写了,每一步都mod 10,然后自然就wa了。。。因为有进位,所以mod 10不行是理所当然的,但是改成mod 1000000之后居然A了,usaco的数据实在是太水了。。这题的正规解法是这样的,就是在计算过程中避免产生进位,也就是消去2和5,这样在mod 10就没有问题了。


Stringsobits
这题算是组合计数求出 (1<<i)是第几个数然后不断逼近就好,但是我没处理好极端情况 (1<<32)-1,wa了好多次,以后交之前应该尽量试一下极端情况。
看了一下解题报告,发现这种思想叫康托展开,恩,学习了


Spinning Wheels
模拟题,模拟转一周期(360度)的情况,刚开始对提议没理解清(1,2和2,3这两个wedge算有重合,我以为没有。。)


Feed Ratios
这题被我用Gauss水掉了。。总感觉数据比较水。。,看了下Analysis,原来还有 Cramer's Rule这种东西。


Magic Squares
bfs,加hash,不过hash我直接用的set。。。


Sweet Butter
spfa+邻接表过,当然还可以用dijkstra+heap


3.3
Riding the Fences 
这题是 euler circuit,不多说


Shopping Offers
简单的背包模型,开了5维数组保存状态。。。


Camelot
bfs+枚举,其中一个减枝很牛X,自己没想到,就是骑士会在国王附近的点接国王。
基本思路(参考NOCOW上的解题报告)
枚举三个点
骑士们在(i,j)点相聚,
某个骑士和国王在(x,y)点相聚,
该骑士初始位置时(p,q)
优化:
1.国王的速度慢,尽量少移动,(x,y)距国王初始位置+-2范围内。
2.如果骑士相聚步数已经大于ans,退出。
这样复杂度就是r*c*(nk+25)*nk


range
递推枚举,dp[k][i][j]表示以(i,j)右下角的长度为k的正方行是否存在,
显然dp[k][i][j] = dp[k-1][i-1][j-1] | dp[k-1][i-1][j] | dp[k-1][i][j-1] | dp[k-1][i][j],当然写的时候dp[i][j]就好,


game1
dp[i][j]表示面对[i,j]区间的数字列先手能赢得最大值,则
dp[i][j] = max(sum[i+1][j]- cal(i+1,j) + a[i],sum[i][j-1] - cal(i,j-1) + a[j])


3.4
fence4 这题跳过。。。对计算几何类题目完全没有兴趣。。。
heritage 输入中序遍历和前序遍历,输出后续遍历。这题被秒杀了。。只能说相比一年前我确实进步了。。
fence9 水枚举
rockers 基础背包,dp[i][j][k]表示第i个盘录第j首歌k时间(最近状态下降不少。。这么水的dp还要想想。。。)


4.1
nuggets
给n个数问最大的不能组成的数,显然这n个数如果最大公约数m不为1的话无解,因为所有非m的倍数的数都不能组成。如果为m == 1,则假设其中gcd(a,b) == 1,a>b,x=k*a,则k从1到a-1,可使x%b取到0到b-1之间所有的数,之后的数都可以通过x加b的倍数得到(感觉我说的还是不太清楚。。),因为a<=256,所以最大不能组成的数不会超过,256×256,根据这个上界dp就好。


fence8
题意:给n根原料木棍boards,r根目标木棍rails,求切原料木棍最多可以却出多少根目标木棍。1<=n <= 50,1<= r <= 1023.
刚开始我的思路就是直接dfs暴力枚举rails去凑boards,但是显然会超时。看了一下hint,说是用dfsid(每次用dfs一层一层的搜),但是觉得既然要求最大值,只能是暴力出所有解啊,怎么能限制层数呢?看了大牛的blog恍然大悟,每层选一个rail,层数=选的rail数目,从小到大枚举rail数目,什么时候无解了,答案也就出来了。然后就开始写,加了写减枝,但还是撑不过第4个点。然后看nocow的题解,根据其减枝策略重写,但有开始wa。。。无奈最后只能取参考大牛代码,看了之后发现大牛的代码简洁优雅,相比之下我的代码就像一砣XX,好了不废话了。。


基本思路:dfsid搜每个rail来源的board
减枝技巧(贴nocow)
1.很容易就能注意到,由于每块rail的价值是相等的——也就是说切小的要比切大的来的划算。那么我们在搜索能否切出i个rail的方案是自然要选最小的i个rail来切。(我居然没有注意到。。00)
2.经过一些实验可以发现,先切大的rail比先切小的rail更容易提前出解。同样先切大的board要比先切小的更快。
3.由于r最大可能是1023,但是rail长度的范围却只有0~128,这点提醒了我们有很多rail的长度会是相同的。所以我们要避免冗余,优化搜索顺序。若有rail[i+1]=rail[i],则rail[i+1]对应的board一定大于等于rail[i]对应的board。可以通过这种方法剪掉很多冗余的枝条。(对于同样大小的tail,无论以何种次序枚举,结果都是一样的,所以只按一种次序来)
4.相应的,如果board[i]=board[i+1],那么从board[i]切下的最大的rail一定大于等于从board[i+1]切下的最大的rail。
5.对于切剩下的board(无法再切下rail),统计一下总和。如果这个值大于board长度的总和减去rail长度的总和,一定无解,可以剪枝。这个剪枝最关键。(也就是现有的board总长小于剩余的tail总长,这个我想到了。。)
6.二分答案.......


Fence Loops
求最小环
这题刚开始的思路是把给的蛋疼图转为正常图,然后对每个每条边删掉进行dijstra,怕tle,就用优先队列,但是不会用priority_queue,正卡的时候,chromium挂了。。打不开了(可能是因为更新的问题),纠结了半天,心情大坏,懒得再搞priotity_quue了,看nocow上说暴力能过,我才反应过来最多100条边,N^3完全没问题啊。。然后用dfs,同时把每条边的邻边分为两个集合,以此判断环。然后居然0ms 1Y。。。
Cryptcowgraphy
这题又是一道神级搜索题。。。关键剪枝是elfhash,但是总的来说我觉得没有fence8复杂。。因为fence8的剪枝不仅难想而且难写。。


基本思想:枚举所有对的C,O,W。。
剪枝(参考nocow)
1.因为会有很多重复的串,所以对每个产生的串进行elfhash,然后判重,这个剪枝非常关键(这个真心没想到。。)
2.任意相邻C,O,W间的串必然是target串的子串。
3.C,O,W字符范围之外的串(前缀,后缀)和原串必然相同的。(这两个并不难想)
4.枚举顺序是O,C,W,而且W是逆序枚举,这样比C,O,W快。(为什么。。。)
5.各种小剪枝。。
这题知道剪枝策旅后,并不难写。。但我还是反了一个很二的错误,在把产生的串的vis状态置为true,我居然在dfs之后“习惯性的”又把它回复成false了。。。这样这个牛X的剪枝就废掉了。。


4.2
Drainage Ditches
这题是最大流基础题。但是我第一次wa了,原因是没加反向弧。其实之前自己一直没理解反向弧的意义,这次接这个机会,好好学习了一下.
在寻找增广路径是我们是一条路一条路找的,比如找到一条增广路S,其容量是k,但这个并不是说在通过最大流时一定有k量的流通过S。实际上在后面找增广路的时候,我们 会进行回流操作,把之前的流推出一部分使得有新的增广路出现。而且这样并不会影响其他边的流量,即之前的已求得的最大流仍然有效,这个大家在纸上花花图应该就明白了。这个反向弧确实是相当巧妙啊。。


The Perfect Stall
最大二分匹配,建一个虚拟的源点和汇点即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值