USACO大量月赛题题解

USACO的题目还是很不错的,就是可惜OJ方面不多,不过搞到了BZOJ的root,这样就能较方便地提交了。

为了方便看题,搞来一本题典,100题,希望能把大多数题目都搞定 //由于版权问题,不能公开这本题典,不过题目已经在列表里了。

按照我的情况,简单题就不发了,容易上当的和难题会发上来


先来一发总表(14.2.6更新)



题号

题目和难度

提示

勘误或注意事项

第0题

★☆☆☆☆ 负二进制 (THE MORONIC COWMPOUTER, 2006 FEB)

和其他转进制一样做,要注意mod出来可能是负的

第1题

★★☆☆☆ 数的幂次 (CRUEL MATH TEACHER, 2009 FEB)

快速幂套高精度即可

第2题

★★★☆☆ 分数变小数 (FRACTIONS TO DECIMALS, 1993 QUALIFYING ROUND)

循环判断,用数组存储每次的余数,当余数出现过一次就停止

输出格式:每行只输出76个字符

第3题

★★★☆☆ 丑数 (HUMBLE NUMBERS, CHAMPIONSHIP)

假设已算出前n个,第n+1个一定是前n个中的一个和一个素数的积

第4题

★☆☆☆☆ 公司利润 (PROFITS, 2011 JAN)

最大连续和

第5题

★☆☆☆☆ 接住苹果 (APPLE CATCHING, 2004 NOV)

dp[n][k]为前n个点正好移动k次的答案

第6题

★★☆☆☆ 方形牛棚 (BIG BARN, 1997 FALL)

用平方时间算出每个点在左方和上方的限制,然后就能DP了

第7题

★★★☆☆ 滑雪课程 (SKI LESSONS, 2009 OPEN)

将课程按结束时间排序,预处理能力值x的情况下最小时间,dp(i,j)为时间为j,前i个课程的答案

第8题

★★★☆☆ 滑雪比赛 (BOBSLEDDING, 2009 DEC)

将时间排序,每个弯角考虑:前一弯的速度,自己的限速,和后面“刹不住”,递推时顺便算答案

第9题

★☆☆☆☆ 自私的奶牛 (SELFISH GRAZING, 2009 DEC)

经典的任务调度问题,按结束时间排序即可

第10题

★★☆☆☆ 重排干草 (HAYBALE RESTACKING, 2012 MAR)

代数分析然后取中位数

同Uva 11300 BZOJ 1045

第11题

★★★☆☆ 奶牛集体照 (COW PHOTOGRAPHY, 2011 DEC)

如果一头牛在另一头牛前面,则它至多在另一头前面2次,以此排序

第12题

★★★★☆ 奶牛集会 (MOOFEST, 2004 OPEN)

V和X都做排序,按V从大往小扫,用数据结构计算x比它小的和与比它大的和

第13题

★☆☆☆☆ 购买饲料 (BUYING FEED 2, 2010 JAN)

以距离+价格为关键字排序

第14题

★★☆☆☆ 保护花朵 (PROTECTING THE FLOWERS, 2007 JAN)

s/t的比值为关键字排序

第15题

★★★☆☆ 奶牛杂技 (COW ACROBATS, 2005 NOV)

w+s为关键字排序

第16题

★★★★☆ 二道工序 (THE MILK QUEUE, 2006 OPEN)

排序关键字 return a.a + b.b + max(a.a, b.b) < a.b + b.a + max(a.b, b.a);

第17题

★☆☆☆☆ 括号序列 (BEST PARENTHESIS, 2011 FEB)

根据题目定义,维护一个栈即可

旧版的翻译有问题,没有说要mod多少

第18题

★★☆☆☆ 向右看齐 (LOOK UP, 2009 MAR)

倒序维护一个单调队列再正序输出

第19题

★★★☆☆ 雄伟的山峦 (MOUNTAIN MAJESTIES, 2002 OPEN)

按起点排序并去除完全覆盖的部分,然后进行扫描,分成两个三角形相交和相离讨论。

题目描述没有提到长度单位,自己随便定一个单位好了

第20题

★☆☆☆☆ 建造道路 (BUILDING ROADS, 2007 DEC)

Kruskal 把已经建好的用并查集合并并计算出大小,有更好的办法,Prim将连通边长设为0

第21题

★★☆☆☆ 奶牛打井 (WATERING HOLE, 2008 OCT)

增加一个点,到每个节点的距离为打一口井的耗费,求mst

第22题

★★★☆☆ 奶牛施工队 (EARTHQUAKE, 2001 OPEN) 

将成本除以V-1减去收益,转化为最大比例生成树

第23题

★★☆☆☆ 翻转棋 (FLIPTILE, 2007 OPEN)

枚举第一行即可

最优解指翻转次数最小的解

第24题

★★★★☆ 电灯 (LIGHTS, 2009 NOV)

每个灯开两次以上没有意义,就可以转化为中途相遇了

第25题

★★★★★ 宝藏图 (TREASURE, 2008 HOL) 

第26题

★★☆☆☆ 奶牛飞盘队 (COW FRISBEE TEAM, 2009 MAR)

分剩余系的背包

第27题

★★★☆☆ 滑雪缆车 (SKI LIFT, 2006 MAR)

设d[i]为i为终点的答案.直接转移是三次方级.维护最大斜率用等积式计算就是平方级的

第28题

★★★☆☆ 奶牛自行车队 (COW CYCLING, FEB 2002)

不妨设每头牛依次做领队,d[i][j][k]为当前第i头牛,第i头牛剩余体力为j,已过圈数为k时的最小答案

第29题

★★★★☆ 打扫食槽 (CLEANING UP, 2009 MAR) 

d[i]<=i所以每个i只需考虑sqer(i)个决策,维护sqrt(i)个区间进行转移

第30题

★★★☆☆ 奶牛探险 (EXPEDITION, 2005 OPEN)

没油时看以前经过的加油站里有最多的加,用优先队列维护,注意先计算后进队

第31题

★★★☆☆ 赞助学费 (FINANCIAL AID, 2004 MAR)

按成绩排序,枚举中位数,两侧各取n/2个最小奖金,用堆进行预处理

第32题

★★★★☆ 奶牛优惠券 (COW COUPONS, 2012 FEB)

将p-c值存进小根堆,对于物品i,可以选择p[i]或c[i]+堆顶元素

第33题

★★★☆☆ 都市地平线 (CITY HORIZON, 2007 OPEN)

将事件按时间排序,扫描并维护优先队列

第34题

★★☆☆☆ 象棋皇后 (CHECKER CHALLENGE, 1993 QUALIFYING ROUND)

枚举即可,注意两条对角线和竖线的剪枝

第35题

★★☆☆☆ 拼图游戏 (JIGSAW PUZZLES, 2008 DEC)

第36题

★★★☆☆ 埃及分数 (BABYLONIAN FRACTIONS, 1997 JAN)

第37题

★★★★☆ 栅栏木料 (FENCE RAILS, 1999 SPRING)

第38题

★★★★★ 解密牛语 (CRYPTCOWGRAPHY, 1998 WINTER)

第39题

★★☆☆☆ 智取金币 (TREASURE CHEST, 2010 DEC)

d[i][j]=a[i]+a[j]-min(d[i+1][j]+d[i][j-1]),但这样是二维的,用点长式可以化成一维空间

第40题

★★★☆☆ 最优回文 (CHEAPEST PALINDROME, 2007 OPEN)

可以把添加操作转化为删除操作,从而变为经典的删数回文

第41题

★★★☆☆ 抢鲜草 (GRAZING ON THE RUN, 2005 NOV)

设DP[l][r][s]为区间(l, r)的答案,s=0代表此时在l位置,s=1代表在r位置,可知在其他位置不划算

第42题

★★★★☆ 提交作业 (TURNING IN HOMEWORK, 2004 OPEN)

第43题

★★☆☆☆ 拖拉机 (TRACTOR, 2012 MAR)

维护两个队列BFS

翻译有问题,n<=50000而且坐标可以是0

第44题

★★☆☆☆ 玉米迷宫 (CORN MAZE, 2011 OPEN)

BFS,注意拓展节点时要记传送后的节点

题意不清,传送时传送且只传送1次,中间点不算经过

第45题

★★★☆☆ 奶牛攀岩 (THE CLIMBING WALL, 2006 OPEN)

暴力建边会超时,可以按y坐标排序,加边的时候判定y坐标是否差1000以下,节省建边时间

"直线距离"指欧几里德距离,第4行"两块直线距离小于1000"应该是"不大于"

第46题

★★★★★ 黄金莲花池 (LILYPAD POND, 2007 FEB)

第47题

★★☆☆☆ 平分子集 (SUBSET SUMS, 1998 SPRING)

背包问题,注意答案可能是0可能是long long

第48题

★★★☆☆ 太空电梯 (SPACE ELEVATOR, 2005 MAR)

按限高排序,再拆物品直接背包,用多重背包的算法更好

第49题

★★★☆☆ 奶牛会展 (COW EXHIBITION, 2003 FALL)

设d[i][x]为前i头牛的子集智商和为x时情商和的最大值,用滚动数组和平移下标实现

第50题

★★★★☆ 股票市场 (STOCK MARKET, 2009 FEB)

将买卖操作分解,从而最大化每天的利益,转化为完全背包

第51题

★★☆☆☆ 数数的梦 (DREAM COUNTING, 2006 DEC)

数位dp,由于数据弱,高效的模拟也能过

第52题

★★★☆☆ 二进制编号 (COW QUEUEING, 2003 DEC)

第53题

★★★☆☆ 开篇第一 (FIRST!, 2012 DEC)

第54题

★★☆☆☆ 时间旅行 (TIME TRAVEL, 2010 OPEN)

第55题

★★★☆☆ 真假奶牛 (LIARS AND TRUTH TELLERS, 2013 JAN)

T代表两头牛属于同一帮派(都说实话或都说谎),用带权并查集实现

第56题

★★★☆☆ 工作安排 (WORK SCHEDULING, 2009 OPEN)

按截止时间从晚到早选择最大收益的工作,用堆维护

第57题

★★★★☆ 导航难题 (NAVIGATION NIGHTMARE, 2004 FEB)

第58题

★★★★☆ 叠积木 (CUBE STACKING, 2004 OPEN)

第59题

★★★☆☆ 奶牛观光 (SIGHTSEEING COWS, 2007 DEC)

二分判断负环

第60题

★★★☆☆ 领取巧克力 (CHOCOLATE GIVING, 2010 FEB)

求一次SSSP即可,写的时候把优先级写反了

第61题

★★★★☆ 道路翻新 (REVAMPING TRAILS, 2009 FEB)

建模,对于边(u,v) (u,k)向(v,k+1)连一条长为0的边,(u,k)向(v,k)连原长度的边,求一次SSSP

第62题

★★★★★ 公路和航线 (ROADS AND PLANES, 2011 JAN)

第63题

★★☆☆☆ 奶牛比赛 (COW CONTEST, 2008 JAN)

对于一个点只需计算和他联通的点数,再转置计算一次,可以直接搜

第64题

★★☆☆☆ 奶牛跨栏 (COW HURDLES, USACO 2007 NOV)

d[i][j]为i出发到j的答案,转移即可

第65题

★★★☆☆ 过路费 (COW TOLL PATHS, 2009 DEC)

先将点权排序,floyd时只有i, j, k可能是点权最大的点,就能转移了

第66题

★★★★☆ 奶牛接力 (COW RELAYS, 2007 NOV)

第67题

★★★☆☆ 录制唱片 (RAUCOUS ROCKERS, 1996 QUALIFYING ROUND)

第68题

★★★★☆ 三个代表 (JERSEY POLITICS, 2005 FEB)

第69题

★★★★☆ 电子游戏 (VIDEO GAME TROUBLES, 2009 DEC)

输入格式的第二行莫名其妙多了几个字

第70题

★★★★☆ 最少找零 (THE FEWEST COINS, 2006 DEC)

第71题

★★★☆☆ 手机网络 (CELL PHONE NETWORK, 2008 JAN)

从下往上,f(i)为覆盖到,g(i)为覆盖到且该点有基站

第72题

★★★☆☆ 道路重建 (REBUILDING ROADS, FEB 2002)

可以看做分组背包问题,d[i][j]为以i为根分离出j个点孤立的最小花费。注意最后枚举每个点作为根更新答案。

第73题

★★★★☆ 产奶比赛 (MILK TEAM SELECT, 2006 MAR)

第74题

★★★★★ 焊接 (SOLDERING, 2011 OPEN)

第75题

★★☆☆☆ 奶牛守卫 (WATCHCOW, 2005 JAN)

很多边的欧拉回路,以边是否访问为状态DFS

第76题

★★★★☆ 明星奶牛 (POPULAR COWS, 2003 FALL)

缩点,拓扑序最低的点才可能是答案

同BZOJ 1051

第77题

★★★★☆ 两条路径 (REDUNDANT PATHS, 2006 JAN)

双联通分量缩点,DAG度为1的点除以2取上整就是答案.注意整张图双连通时答案为0

第78题

★★★☆☆ 修剪草坪 (MOWING THE LAWN, 2011 OPEN)

标准的单调队列优化

第79题

★★★☆☆ 玉米实验 (CORNFIELDS, 2003 MAR)

二维RMQ,也可以用单调队列预处理

第80题

★★★★☆ 又买饲料 (BUYING FEED, 2010 NOV)

输入格式“第二行到第K+1行”

第81题

★★★★☆ 干草塔 (TOWER OF HAY, 2009 OPEN)

第82题

★★★★☆ 土地并购 (LAND ACQUISITION, 2008 MAR)

按h升序再按w升序排序,去掉能被完全覆盖的土地,这样h就单调增,w单调减,转换成标准斜率优化

第83题

★★★☆☆ 奶牛抗议 (GENERIC COW PROTESTS, 2011 FEB)

DP方程式显然,用BIT优化即可,注意将sum数组离散化会方便不少,也不会爆内存

第84题

★★★☆☆ 奶牛赛跑 (RUNNING LAPS, 2012 OPEN)

平方算法显然,nlogn可以把每头牛的时间分成整数部分和小数部分,整数部分求和小数部分求逆序数对

第85题

★★★★☆ 道路植草 (GRASS PLANTING, 2011 DEC)

第86题

★★★★☆ 懒惰奶牛 (LAZY COWS, 2005 OPEN)

第87题

★★★★☆ 洞穴奶牛 (CAVE COW 1, 2004 OPEN)

第88题

★★★★☆ 安排牧场 (CORN FIELDS, 2006 NOV)

第89题

★★★★☆ 奶牛猜数 (HAYBALE GUESSING, 2008 JAN)

二分答案.将A值降序枚举,对于相同的A值集合取交集和并集,交集中必须要有空点.并集区间修改,可以离散化或并查集加速

第90题

★★★★☆ 跨栏训练 (FENCE OBSTACLE COURSE, 2004 DEC)

第91题

★★★★☆ 预定旅馆 (HOTEL, 2008 FEB)

对于一段区间,k连续区间只可能出现在左半、左半+右半、右半三种可能,用线段树维护,类似最大连续和

第92题

★★★★★ 修路 (CONNECT, 2007 OPEN)

第93题

★★★★☆ 挑剔的美食家 (GOURMET GRAZERS, 2007 DEC)

第94题

★★★★☆ 约翰的书架 (BOOKSHELF, 2012 OPEN)

第95题

★★★★★ 期末总评 (COW SCHOOL, 2007 JAN)

第96题

★★★☆☆ 奶牛晚宴 (DINING, 2007 OPEN)

把每头牛拆成2头牛,连长度为1的边,把食物和要吃它的奶牛连接,饮料类似,加一个起点一个终点,用DFS的最大流就能过

第97题

★★★☆☆ 地震破坏 (EARTHQUAKE DAMAGE 2, 2009 MAR)

拆点最小割,将节点u拆成u,u' u'向u连一条容量为1的边,图中其他边将容量设为INF,报告的点向超级汇点连容量是INF的边

第98题

★★★★☆ 小行星群 (ASTEROIDS, 2006 NOV)

以行和列作为二分图的点,一个位置作为二分图的边,要求最小点覆盖,数值上等于最大匹配

来源应该是05NOV,同Uva 11419

第99题

★★★★★ 玩具消毒 (TOYS, 2008 NOV)

同BZOJ 1221

 


 



 



 


然后是一些题目的题解


第3题,丑数 Humble 


http://blog.csdn.net/qyl916/article/details/18894047


第6题,方形牛棚 bigbrn  第8题 滑雪比赛 bobsled


http://blog.csdn.net/qyl916/article/details/18894055


第10题 重排干草 Restack  第11题 奶牛集体照 photo


http://blog.csdn.net/qyl916/article/details/18894529


第15题 奶牛杂技 acrobat  第16题 两道工序 mqueue


http://blog.csdn.net/qyl916/article/details/18948601


第20题 建造道路 roads
典型的MST,只是Kruskal之前要把已经合并的边合并了,并计算事先多少个点已经联通

注意并查集的合并是把代表元素进行赋值


const int maxn=1010,maxm=1000010;
int n,m,x[maxn],y[maxn],fa[maxn],u[2*maxm],v[2*maxm],len,p[2*maxm];
double w[2*maxm];
int cmp(int x0,int y0){
    return w[x0]=n-1)break;
        ++st;
        //write1(st);
        
    }
    printf("%.2f\n",ans);
    
}
int main()
{
    setio("roads");
    len=0;
    read2(n,m);
    REP1(i,n)read2(x[i],y[i]);
    REP1(i,n)REP1(j,n){
        u[len]=i;v[len]=j;
        w[len]=sqrt( ( (double)x[i]-x[j] )*( (double)x[i]-x[j] ) +( (double)y[i]-y[j])*((double)y[i]-y[j])); len++;
        
    }
    //REP(i,2*n*n)printf("%d %d %d %f\n",i,u[i],v[i],w[i]);
    kruskal();
	//system("pause");
    return 0;
}

但这题用Kruskal是很糟糕的,用Prim把边长设为0更好。


const int maxn = 1010;

int x[maxn], y[maxn];
double  g[maxn][maxn], minv[maxn];
int n, m, used[maxn];

double prim(){
    rep1(i, n) minv[i] = INF;  CLR(used, 0); minv[1] = 0;
    double ans = 0;
    while(1){
        int u = -1;
        rep1(i, n) if (!used[i] && (u==-1 || minv[u] > minv[i]) ) u = i;
        if (u == -1) break; 
        ans += minv[u];
        used[u] = 1;
        rep1(i, n) minv[i] =min (minv[i], g[u][i]);
    }
    return ans;
}
int main()
{
	scanf("%d%d", &n, &m);
	rep1(i, n) scanf("%d%d", &x[i], &y[i]);
	rep1(i, n) rep1(j, n) g[i][j] = sqrt( .0 + (double)(x[i] - x[j]) * (x[i] - x[j]) 
    + (double)( y[i] - y[j] ) *( y[i] - y[j]) );
    //rep1(i, n) printf("%d %d\n", x[i], y[i]);
	rep(i, m) {
        int u, v;
        scanf("%d%d", &u, &v);
        g[u][v] = g[v][u] = 0;
    }
    //rep1(i, n) {rep1(j, n) printf("%.2f ", g[i][j]); PN;} 
    double ans = prim();
    printf("%.2f\n", ans);
    //while(1);
    return 0;
}


第39题 智取金币 treasure

这题是明显的区间DP,方程式并不难写,但5000*5000的数组会爆USACO的16MB内存,所以需要简化。

这里有一个很经典的技巧,区间DP的计算顺序是按区间从短到长顺序的。所以可以换一种方程式的写法。

原来是d(l, r) 现在以左指针和区间长度来定义。原来的d(l, r)变成了d(l, r-l+1) 也称点长式。

这样的转移方式就能用滚动数组优化空间了。


换新的编译器就TLE了
似乎只是常数问题 
改成递推,快了4倍
AC 
bzoj上有MLE的问题
改成滚动数组 
*/ 
void setio(string name){
	string in_f=name+".in";
	string out_f=name+".out";
	freopen(in_f.c_str(),"r",stdin);
	freopen(out_f.c_str(),"w",stdout);
}
int c[5010],s[5010],d[5010];

int main()
{
    //setio("treasure");
    int n;read(n);
    REP1(i,n)read(c[i]);
    s[0]=0;
    REP1(i,n)s[i]=s[i-1]+c[i];
    REP1(i,n)d[i]=c[i];
    REP1(l,n-1)
    REP1(i,n-l)
    d[i]=s[i+l]-s[i-1]-min(d[i+1],d[i]); 
    writeln(d[1]);
	//system("pause");
    return 0;
}


第40题 最优回文 cheappal


拿到这题没想法,只能删除的话是容易的DP,但加插入就完全没法转移了。

其实删除操作等价于在另一端插入,插入操作等价于在另一侧删除,这样就能转化成标准的区间DP了。

int cost[200], d[2010][2010], n, m;
char s[2010];
int dp(int l, int r){
    int &ans = d[l][r];
    if (ans != -1) return ans;
    if (l >= r) {ans = 0; return ans;}
    ans = 0;
    if (s[l] == s[r]) ans = dp(l + 1, r - 1);
    else ans = min( dp(l, r - 1) + cost[s[r]], dp(l + 1, r) + cost[s[l]] );
    return ans;
}
int main()
{
    scanf("%d%d", &n, &m); 
	scanf("%s", s);
	rep(i, n){
        char c;int c1, c2;
        scanf(" %c%d%d", &c, &c1, &c2);
        cost[c] = min(c1, c2);
    }
    CLR(d, -1);
    printf("%d\n", dp(0, m - 1) ); //while(1);
    return 0;
}


 


你可能感兴趣的:(USACO大量月赛题题解)