
USACO题解
文章平均质量分 55
accepoc
这个作者很懒,什么都没留下…
展开
-
USACO6.1.1 Postal Vans (vans) 插头dp
题意:一个4*n的矩阵,从左上角出发,经过每个顶点恰好1次回到左上角,问有多少种走法。第一道插头dp……磕磕绊绊总算过了……什么是插头dp请参考cdq的论文《基于连通性状态压缩的动态规划问题》。注意同样的路径,正着走和反着走算两条不同的,所以最后答案要乘2。然后加上高精就行了。代码(括号表示法):/*ID:shijiey1LANG:C++PROG:vans*/原创 2014-12-26 09:50:41 · 754 阅读 · 0 评论 -
USACO3.3.3 Camelot (camelot)
先将坐标离散化。每个点向此处有骑士能走到的8个点连边。然后以每个骑士为源点spfa,只不过记录距离时每个点要拆成两个点,接国王和不接国王。dist[i][j][k]:以第i个骑士(离散化后的坐标)为源点,到第点j(离散化后的坐标),k=0不接,k=1接国王的最短路。扩展的时候,dist[i][j][stat]扩展到dist[i][next_j][stat],然后还需判断,若stat原创 2014-12-10 09:20:12 · 442 阅读 · 0 评论 -
USACO3.3.4 Home on the Range (range)
dp[i][j]:以点(i,j)为右下角能取到的最大正方形的边长若arr[i][j]==0,则dp[i][j]=0否则dp[i][j]=min(dp[i - 1][j], min(dp[i][j - 1], dp[i - 1][j - 1])) + 1/*ID:shijiey1PROG:rangeLANG:C++*/#include #include #include u原创 2014-12-10 09:21:07 · 671 阅读 · 0 评论 -
USACO3.3.5 A Game (game1)
状态:dp[l][r]:序列还剩[l,r]时先手取的最大得分则现在有两种选择:取l和取r。若取l,下一步换另一个人取的最大得分为dp[l+1][r],所以这一步的最大得分dp[l][r]=sum[l,r]-dp[l+1][r]若取r同理。即dp[l][r] = max(sum[l,r]-dp[l + 1][r], sum[l][r]-dp[l][r+1]);/*ID:shijiey1原创 2014-12-10 09:22:02 · 647 阅读 · 0 评论 -
USACO3.4.1 American Heritage (heritage)
已知树的前序,中序遍历,求后序遍历。中序遍历(in):左-根-右前序遍历(pre):根-左-右后序遍历(post):左-右-根可以发现,整棵树的根,在前序遍历的第一个字符,也是后序遍历的最后一个字符'R' l1 l2in: ----R*** l1 l2pre: R----*** l1 l2post:----***R先把后序遍历原创 2014-12-10 09:22:53 · 417 阅读 · 0 评论 -
USACO3.4.2 Electric Fence (fence9)
皮克定理/*ID:shijiey1PROG:fence9LANG:C++*/#include #include #include using namespace std;int n, m, p;int gcd(int a, int b) { while (b ^= a ^= b ^= a %= b); return a;}int main() { freope原创 2014-12-10 09:24:01 · 488 阅读 · 0 评论 -
USACO3.4.3 Raucous Rockers (rockers)
dp[i][j][k]:考虑了前i首歌,装进了j张cd,最后一张cd用了k分钟能装下的最多的歌曲的数目。初始状态:dp[1][1][0]=0,dp[1][1][arr[1]=1(arr[1]转移(顺推):dp[i + 1][j][k] = max(dp[i][j][k], dp[i + 1][j][k]) (不装第下一张cd)dp[i + 1][j + 1][arr[i + 1]] =原创 2014-12-10 09:24:44 · 368 阅读 · 0 评论 -
USACO4.1.1 Beef McNuggets (nuggets)
所有方案都能满足的情况:当且仅当输入里的n个数里有1。否则1一定是一个解。不存在不能满足的上限:计算出输入中最大的两个数的最小公倍数x,如果比x大的数有一个不能满足,则不存在不能满足的上限。然后就是用背包问题统计某个数是否可以取到。/*ID:shijiey1LANG:C++PROG:nuggets*/#include #include #include using nam原创 2014-12-10 09:25:50 · 601 阅读 · 0 评论 -
USACO4.1.2 Fence Loops (fence6)
将篱笆看作点,两段连接的篱笆之间连边,权值为两篱笆长度之和。floyd最小环,然后结果除以2就是答案。/*ID:shijiey1PROG:fence6LANG:C++*/#include #include #include #include #include #define INF 0x3f3f3f3fusing namespace std;int edges[1原创 2014-12-10 09:26:35 · 432 阅读 · 0 评论 -
USACO3.3.2 Shopping Offers (shopping)
因为n然后就记忆搜吧,没什么技术含量。/*ID:shijiey1PROG:shoppingLANG:C++*/#include #include #include #define INF 0x3f3f3f3fusing namespace std;int s, b, m;// shop[i][0]表示第i种优惠的价格,shop[i][1],shop[i][2],sh原创 2014-12-10 09:19:33 · 490 阅读 · 0 评论 -
USACO3.3.1 Riding The Fences (fence)
欧拉路。如果有节点的度数为奇数,则以它作为起点,否则以编号最小的点做起点(注意题目没说节点是从1开始标号的)dfs然后倒序输出。至于为什么倒序才能保证字典序其实我也不知道。/*ID:shijiey1PROG:fenceLANG:C++*/#include #include #include #define INF 0x3f3f3f3fusing namespace原创 2014-12-10 09:13:58 · 566 阅读 · 0 评论 -
USACO3.1.4 Contact (contact)
略水。枚举长度l从a到b,找出字符串中所有长度为l的字串然后用map记录,排序输出。/*ID:shijiey1PROG:contactLANG:C++*/#include #include #include #include #include #include #include using namespace std;struct Num { string nu原创 2014-12-10 09:03:42 · 783 阅读 · 0 评论 -
USACO3.1.5 Stamps (stamps)
dp[i]表示要得到i元钱需要几张邮票。初始状态:dp[0]=0然后递推,对于每一个dp[i]/*ID:shijiey1PROG:stampsLANG:C++*/#include #include #include using namespace std;int n, m;int arr[65];int dp[2000010];int min(int a, i原创 2014-12-10 09:04:29 · 399 阅读 · 0 评论 -
USACO3.2.1 Factorials (fact4)
一边乘一边模,末尾有0就去掉。也有更好的做法就是遇到2和5continue。/*ID:shijiey1PROG:fact4LANG:C++*/#include #include #include #include using namespace std;int n;int s = 1;int main() { freopen("fact4.in", "r",原创 2014-12-10 09:05:17 · 377 阅读 · 0 评论 -
USACO3.2.2 Stringsobits (kimbits)
dp[j][k]表示长度为j的串中有不多与k个1的个数所以dp[j][k] = dp[j][k-1]+c[j][k].边界:dp[j][0]=dp[0][j]=1然后从n到1枚举k,每次输出所求串的从右到左第k位。如果dp[k-1][l]如果dp[k-1][l]>=I,则这一位一定填0,原因类似上面。/*ID:shijiey1PROB:kimbitsLANG:C++原创 2014-12-10 09:06:10 · 383 阅读 · 0 评论 -
USACO3.2.3 Spinning Wheels (spin)
因为每个轮子转360次一定会回到原位,所以360秒之后还没有结果就说明无解。每次转动之后枚举0到359的每一个位置如果符合则输出。/*ID:shijiey1PROB:spinLANG:C++*/#include #include #include #include using namespace std;int speed[6];int wheel[5][360];原创 2014-12-10 09:07:01 · 604 阅读 · 0 评论 -
USACO3.2.4 Feed Ratios (ratios)
其实就是求一个最简配比a,b,c,t使a(x1,y1,z1)+b(x2,y2,z2)+c(x3,y3,z3)=t(k1,k2,k3)用行列式求出a,b,c,t。如果t=0或abct不同号则说明无解。否则分别除以gcd输出就行了。/*ID:shijiey1PROG:ratiosLANG:C++*/#include #include #include using namesp原创 2014-12-10 09:07:57 · 427 阅读 · 0 评论 -
USACO3.2.5 Magic Squares (msquare)
标准的宽搜,应该没什么难度吧。/*ID:shijiey1PROG:msquareLANG:C++*/#include #include #include #include #include #include #include using namespace std;struct Node { int deep; string stat, trans; Node(原创 2014-12-10 09:08:42 · 540 阅读 · 0 评论 -
USACO3.2.6 Sweet Butter (butter)
枚举每一个集合点,n次spfa。/*ID:shijiey1PROG:butterLANG:C++*/#include #include #include #include #include #define INF 0x3f3f3f3fusing namespace std;struct Edge { int to, v;};int n, V, E;int a原创 2014-12-10 09:09:35 · 437 阅读 · 0 评论 -
USACO4.2.1 Drainage Ditches (ditch)
裸的最小割,跑一遍最大流。/*ID:shijiey1PROG:ditchLANG:C++*/#include #include #include #include #include #define MAXV 205#define INF 0x3f3f3f3fusing namespace std;struct Edge{ int from, to, cap, fl原创 2014-12-10 09:27:27 · 260 阅读 · 0 评论 -
USACO4.2.2 The Perfect Stall (stall4)
二分图匹配,匈牙利算法即可。数据范围不大最大流也能过。/*ID:shijiey1PROG:stall4LANG:C++*/#include #include #include #include using namespace std;int n, m;vector edges[205];int mat[205];int done[205];void addEd原创 2014-12-10 09:28:17 · 484 阅读 · 0 评论 -
USACO5.3.2 Window Area (window)
矩形切割。执行非查询操作时更新高度,创建窗体和置顶时时height[i]=top++,置底height[i]=bot--,删除窗体时vis[i]=false。执行查询操作时dfs,每次用比窗口i高一层的窗体把i切割成最多4个矩形,然后递归。这种方法叫上浮法,对于当前dfs的窗口i,想象它向上浮,遇上了第一个比它高的矩形,被它切成了最多4个矩形,然后4个小矩型再继续上浮,直到露出水面时剩原创 2014-12-10 09:41:09 · 444 阅读 · 0 评论 -
USACO5.3.3 Network of Schools (schlnet)
先用tarjan缩点。第一问的解就是缩点后所有没有入度的点,因为没有学校给会它们传软件,它们必须要接受新软件副本。第二问的解没有入度与没有出度的点个数较多的数目。因为所有没有入度的点必须给它一条入边,没有出度的点必须给它一条出边。这题还须要特判,如果缩点后只有一个点,则输出1,0/*ID:shijiey1LANG:C++PROG:schlnet*/#include #inc原创 2014-12-10 09:41:52 · 351 阅读 · 0 评论 -
USACO5.3.4 Big Barn (bigbrn)
巨水的dp题arr[i][j]记录是否有树,1表示有0表示无dp[i][j]表示以点(i,j)为右下角的最大0正方形的边长。若arr[i][j]==0,dp[i][j]=0否则dp[i][j]=min(dp[i - 1][j], min(dp[i][j - 1], dp[i - 1][j - 1])) + 1/*ID:shijiey1LANG:C++PROG:bigbrn*原创 2014-12-10 09:42:46 · 507 阅读 · 0 评论 -
USACO5.4.1 Canada Tour (tour)
可以看做从起点出发走两条线到终点。dp[i][j]表示第一条线走到i,第二条线走到j的最多经过的城市数。枚举max(i,j)之后的每一个城市k,下一步可以i走到k也可以j走到k。dp[i][k] = max(dp[i][k], dp[i][j] + 1)dp[k][j] = max(dp[k][j], dp[i][j] + 1)/*ID:shijiey1PROG:tourLA原创 2014-12-10 09:44:02 · 548 阅读 · 0 评论 -
USACO5.5.1 Picture (picture)
先处理所有的横线,竖线同理。横边记录一个pos值,每个矩形有两条横边,下面的pos记为1,上面的pos记为-1。将所有横边按y坐标由小到大排好序,然后枚举,横坐标上的每个点记录一个值layer。每遇到一条边i,对于边i上的每一个点x,layer[x]+=i.pos。如果layer[j]从0变为1,周长ans++,如果layer从1变为0,同样ans++。注意矩形的顶点只能算一次,在原创 2014-12-10 09:46:16 · 492 阅读 · 0 评论 -
USACO5.4.3 TeleCowmunication (telecow)
先拆点,每个点i拆成i和i+n,连一条边,容量为1。对于原图中相连的两个点i和j,i+n到j,j+n到i各连一条容量为INF的边。第一问最小割,跑一遍dinic。第二问最小点割集,枚举每一个点i将其删去(将i与i+n之间的边的容量设为0),再跑一遍dinic,如果流量flow'等于原流量flow-1,则该点一定在最小割集中,flow-=1,继续枚举。如果flow'!=flow-1,将该原创 2014-12-10 09:45:39 · 488 阅读 · 0 评论 -
USACO5.5.2 Hidden Passwords (hidden)
后缀数组。将字符串扩展成两倍,在末尾接上一个极大值(因为我用0~25表示字母,所以最后接上了一个26),然后计算后缀数组。从前向后扫一遍后缀数组,遇到sa[i]<len(S)就直接输出sa[i](S是原字符串,不是扩展后的字符串)。/*ID:shijiey1PROG:hiddenLANG:C++*/#include #include #include #include原创 2014-12-10 09:47:16 · 436 阅读 · 0 评论 -
USACO4.4.1 Shuttle Puzzle (shuttle)
找规律。4 35 642 1357 642 35 4 (n=3)5 46 753 2468 97531 2468 753 46 5 (n=4)/*ID:shijiey1PROG:shuttleLANG:C++*/#include #include #include #include #include #include #include using name原创 2014-12-10 09:32:50 · 522 阅读 · 0 评论 -
USACO5.3.1 Milk Measuring (milk4)
用dfsid枚举每一种取法,然后用完全背包判断是否符合题意。不会超时。/*TASK:milk4ID:shijiey1LANG:C++*/#include #include #include #include #include using namespace std;int m, n;int arr[105];set pail;int min(int a, int原创 2014-12-10 09:39:48 · 514 阅读 · 0 评论 -
USACO5.2.1 Snail Trail (snail)
水题。n/*ID:shijiey1LANG:C++PROG:snail*/#include #include #include #include using namespace std;int n, m;int arr[123][123];int cnt = 0;int maxcnt = 0;int vis[123][123];int dx[4] = {-1,原创 2014-12-10 09:38:45 · 494 阅读 · 0 评论 -
USACO4.2.3 Job Processing (job)
先进行工序a。因为所有的产品都同时放在输入库中,所以这一步直接贪心,只要有空闲的机器,就从输入库中取出产品放进去。这样工序a完成的时间一定是最短的,如下图 开始1 | --------2 | ------3 | ----4 | ---5 | -然后进行工序b。这是因为每件产品完成工序a的时间不同,所以不能像上一步一样做。那怎么办呢?我们可以把工序b想象成用机原创 2014-12-10 09:29:02 · 453 阅读 · 0 评论 -
USACO4.3.1 Buy Low, Buy Lower (buylow)
第一问最长下降子序列,len[i]表示以i结尾最长下降子序列的长度。第二问求最长下降子序列的个数。cnt[i]为以i结尾最长下降子序列的个数。对于所有的位置i枚举每一个j(1arr[i],若len[j]+1>len[i],cnt[j]=cnt[i],否则若len[j]+1==len[i],cnt[j]+=cnt[i]。因为题目要求不重复,所以记录一个next数组,next[i]表示i右原创 2014-12-10 09:30:28 · 467 阅读 · 0 评论 -
USACO4.3.2 Street Race (race3)
第一问n-2次spfa,枚举每一个不可避免的路口k,spfa时遇到k时continue,如果从起点无法走到终点则k为不可避免的路口。第二问,显然中间路口一定是一个不可避免路口,所以先枚举每一个不可避免路口k,以k为起点spfa,如果从比k编号小的节点回到了k,则k一定不是中间路口。否则k一定是中间路口。/*ID:shijiey1PROG:race3LANG:C++*/#include原创 2014-12-10 09:31:08 · 424 阅读 · 0 评论 -
USACO4.3.3 Letter Game (lgame)
第一步先从字典里筛选出所有符合条件的串。看似数据很大其实第一步筛出来已经没剩几个了,枚举就行。/*ID:shijiey1PROG:lgameLANG:C++*/#include #include #include #include #include #include #include using namespace std;struct Pair{ string原创 2014-12-10 09:32:04 · 448 阅读 · 0 评论 -
USACO4.4.2 Pollutant Control (milk6)
第一问最小割,跑一遍最大流即可。第二问最少删去几条边,只需在求最大流时将每条边的权值,假设原来是c,现在设为c*1001+1,最后的最大流ans除以1001还是第一问答案,ans%1001就是第二问答案。至于第三问最小边割集,正解应该是枚举删去每一条边,再跑一次最大流,如果流量正好是原流量减去这条边的容量则这条边一定在最小边割集中,删去这条边,总流量减去这条边的流量继续枚举。但是也可以原创 2014-12-10 09:34:08 · 446 阅读 · 0 评论 -
USACO4.4.3 Frame Up (frameup)
用1~26表示每种字母统计每种字母的最小与最大的x与y坐标,这样就知道了每个矩形的边框。从最上层开始dfs,找到当前所有边框上都是同样数字的矩形,则这个矩形一定是最上层的,继续dfs。每次dfs找到一个矩形时,将该矩形的边框上的所有数字设为负数,负数可以看作是任何一种数字。回溯时再还原。dfs到最后一层时记录答案,最后排序输出。/*ID:shijiey1LANG:C++PRO原创 2014-12-10 09:34:52 · 534 阅读 · 0 评论 -
USACO5.1.1 Fencing the Cows (fc)
裸的凸包。graham-scan水过。/*ID:shijiey1PROG:fcLANG:C++*/#include #include #include #include #include using namespace std;struct Point { double x, y;};double dist(Point a, Point b) { retur原创 2014-12-10 09:35:53 · 397 阅读 · 0 评论 -
USACO5.1.3 Musical Themes (theme)
dp[i][j]表示第一个串匹配到了i,第二个串匹配到了j的最长公共部分的长度。只不过这题不能直接匹配,要计算后一个和前一个的差值再匹配。dp[i][j]=max(dp[i][j],dp[i-1][j-1]) (arr[i]-arr[j]==arr[i-1]-arr[j-1])因为不能有重复部分,所以当i-dp[i-1][j-1]-1>j时才进行dp。用滚动数组实现。/*ID:s原创 2014-12-10 09:36:33 · 701 阅读 · 0 评论 -
USACO3.1.3 Humble Numbers (humble)
已经知道前k个丑数,如何得到第k+1个丑数?对于每个质数p,找到最小的丑数h,使得h*p比上一个丑数大,所有的h*p中最小的就是下一个丑数。但这样会很慢,所以需要一个pindex数组记录每个质数乘到了哪一个丑数。//其实就是官方题解/*ID:shijiey1PROG:humbleLANG:C++*/#include #include #include #includ原创 2014-12-10 09:01:24 · 374 阅读 · 0 评论