USACO3.3题目简析

chunlvxiong的博客


T1:Riding the Fences

  题意:给出M条边(1≤M≤1024,点数不超过500),输出这个图的欧拉路(保证一定存在)字典序最小的方案。

  直接DFS即可,但字典序较难处理。首先从一个可行的字典序最小的点进行DFS,每次选择字典序小的点进行DFS(用邻接矩阵存储会较好处理),当所有点处理完后,将这个点压入栈中(而不是在开始压入栈中,否则选择字典序最小的点进行DFS不能保证字典序),最后倒序输出即可。

  注意这个栈的大小是maxm(最大边数)而不是maxn(最大点数)。

T2:Shopping Offers

  题意:有s(1≤s≤99)种优惠方案,每种优惠方案包括n中商品(1≤n≤5),并输入每种商品的编号c(1≤c≤999)和数量k(1≤k≤5),以及最后整套优惠方案的价格(保证一定比原价便宜)。需要购买b(1≤b≤5)种商品,并输入每中商品的编号c(1≤c≤999),需要购买的数量k(1≤k≤5)和原价p(1≤p≤999)。

  由于需要购买的商品种类和数量都很少,可以考虑多维状态存储的DP来解决此问题。以b=5为例,即dp[a1][a2][a3][a4][a5]表示第一种商品买了a1个……第五种商品买了a5个的最少价格,dp数组的初始值是按原价买的结果,方程容易写出。这样操作的时间复杂度为O(6^5*99*5),是可以A掉此题的。

  但是由于b的值不一定,多维状态DP不方便,因此考虑使用状压DP。由于每种商品的个数为0..5,所以可以采取六进制存储完成状压。DP时直接0..6^b-1按序DP即可(假设a>b,那么a一定至少有一件商品比b买的多,因此a无法向b转移,从而也就保证了转移是按序进行的)。

  这样就可以较好地解决这个问题了。

T3:Camelot

  题意:有一个r*c的矩阵(1≤r≤26,1≤c≤40),其中有N个骑士(没有两个骑士处于同一位置,也可能没有骑士)和一个国王,走法与国际象棋中的一样,现在要使N个骑士和国王抵达同一个汇合点,其中如果一个骑士和国王除以同一位置那么骑士可以和国王一起以骑士姿态行进,步数只算骑士的。问最少多少部汇合。

  这题非常的坑……比较暴力的做法是:先依靠预处理算好每个点与每个点之间的距离(按骑士方式或是国王方式)穷举每个汇合点,。再穷举国王与骑士的交汇点以及与国王汇合的骑士,依靠预处理算好距离,再更新最小值。但这样做法是O(r^2c^2n)的,而n最大可以达到rc,也就是说最坏复杂度O(r^3c^3),会T。

  其实如果骑士要绕路去接国王的话并不会赚,因为它还要回来(也就是两倍步数),还不如骑士原地不动等国王过来。

  因此你可以让骑士直接走最短路,然后让国王到达最近的骑士经过的点即可。具体实现就是:先对于汇合点做一次BFS,然后你要把骑士经过的路打上标记(注意,骑士的最短路可能由多条,都要打上标记,这里你可以这样操作:例如x1,y1从x2,y2或x3,y3过来都是最短路,那么你先把x2,y2和x3,y3都打上标记,然后分别再对x2,y2和x3,y3的最短路打标记,如果x2,y2或x3,y3的最短路已经打好了标记,就不用再打了,这样总复杂度O(rc)的),再对国王做一次BFS找到最近的打过标记的点即可算出距离,更新最小值即可。

T4:Home on the Range

  题意:一个N*N的正方形(1≤N≤250),其中有些格子是损坏的,求出所有格子均完好的i*i(1≤i≤N),若=0则不输出)的子正方形个数。

  考虑直接穷举每个位置作为正方形左上角以及边长,然后判断这个正方形是否是完好的。

  利用前缀和优化可以将判断的复杂度降为O(1),这样的总复杂度就是O(N^3)的,可以顺利A掉此题。

T5:A Game

  题意:两个人玩游戏,每次从N(1≤N≤100)的序列中取数,只能取头或尾,两人都尽力使最后得分最高。问两个最后各得几分。

  考虑用dp[i][j]表示剩余范围i到j,先手能拿的最多分数。则方程如下(用sum[i]表示前缀和):

  dp[i][j]=max{sum[j]-sum[i]-dp[i+1][j]+a[i],sum[j-1]-sum[i-1]-dp[i][j-1]+a[j]}

  最后第一个人的分数为dp[1][n],第二个人的分数为sum[n]-dp[1][n]。

转载于:https://www.cnblogs.com/chunlvxiong/p/7411055.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值