英文原题 中文题译
大意:在棋盘上方若干个骑士和一个国王,要让他们汇聚到一个格子上,其中骑士带上国王走这样国王上马之后不计代价。问,汇集他们的最小代价是多少步。(骑士走马步,国王走任意一相邻格)。
国王到每个点的距离是已知的,即为行列差之和。因此,只要考虑骑士:
对棋盘上的每个格子作为汇聚点做枚举(26*30)。从该节点出发作宽度优先搜索,如果有骑士所在的格子不能到达,则放弃。否则,宽搜时记录的轨迹可得到每个骑士到汇集点的路径,让国王到路径上最近的格子与骑士回合,计算得到使用该汇集点的总代价。
这个算法似乎有问题,骑士可以为了捎带国王而绕路,或者选择走不同的最优路径。我们无法保证在上面记录路径的时候记录的是最靠近国王的那个。
因此,不记录路径,而记录点对之间的最短距离。首先计算出按骑士走法的棋盘上任意两点间的最短距离,之后,对每个汇聚点,首先考虑国王的走法,是否需要骑士携带,或者自己走到汇聚点:设汇聚点为H,国王位置为K,有N[i]个骑士,则若有骑士在位置P接应国王,那么其代价为Kdis(K,P)+min{Ndis(N[i],P)+Ndis(P,H)-Ndis(N[i],H)},在这个代价中找最小的P和H,即为国王上马的最小代价,再与国王自己走到目标点的代价Kdis(K,H)比较取其小的。
如果P的选取范围是全棋盘,那么能确保得到最优解。不过这样会超时(时间代价为O(m^2*n^2*k)其中m,n为行列数,k为骑士数,而骑士最多为m*n,则代价为O(N^3)(N=m*n为棋盘大小)。修改为国王周边正负2格,程序通过。不过这很显然是不能保证最优解,不过,考虑到棋盘本身不大,也就这样吧。
最后,这个方法的时间和空间复杂度都是可以优化的,比如:
1. 考虑棋盘的对称性,计算最小距离矩阵时只需计算1/4即可。
2. 数组下标直接引用修改为按指针访问,至少可以提升一半的效率。
3. 棋盘按二维数组访问可修改为展开成一维。有意思的是,展开成一维之后,会发现这和3.2.6极为相似。事实上,如果没有国王,只有骑士,这两个题就一个是在加权图,一个在非加权图上而已。我们考虑这样一个变化版本:在草原上,骑士必须沿着管道走,国王可以走捷径。骑士和国王分布在若干个据点内,现在要集中起来开会,国王可以在某个据点上骑士的马,这样,之后计算距离就不计国王了。那么,给定据点分布和道路图,问,在哪个据点开会代价最小?
/* ID: blackco3 TASK: camelot LANG: C++ */ #include <iostream> #include <memory.h> using namespace std; const int _max_row_(26), _max_col_(30); int n_row, n_col, n_knight ; struct t_chess { int row, col ; } king , knights[_max_row_*_max_col_] ; int min_dis[_max_row_][_max_col_][_max_row_][_max_col_] ; int drow[8]={2, 2, -2, -2, 1, 1, -1, -1 } ; int dcol[8]={1, -1, 1, -1, 2, -2, 2, -2 } ; int dis[_max_row_][_max_col_] ; t_chess queue[_max_row_*_max_col_] ; void get_min_dis(int crow, int ccol){ memset( dis, 0xff, sizeof(dis) ); t_chess *head=queue, *tail=queue ; tail->row=crow, tail->col=ccol, tail++, dis[crow][ccol]=0 ; register int hrow, hcol, ndis, nrow, ncol, dir ; do{ hrow=head->row, hcol=head->col, ndis=dis[hrow][hcol]+1, head++ ; for( dir=0; dir<8; dir++ ){ nrow = hrow + drow[dir], ncol = hcol + dcol[dir] ; if( nrow<0 || nrow>=n_row || ncol<0 || ncol>=n_col || dis[nrow][ncol]!=-1 ) continue ; tail->row=nrow, tail->col=ncol, tail++, dis[nrow][ncol] = ndis ; } } while ( head != tail ) ; for( int ir=0; ir<n_row; ir++ ) for( int ic=0; ic<n_col; ic++ ) min_dis[crow][ccol][ir][ic] = dis[ir][ic] ; } int help_knight[_max_row_][_max_col_], king_dis[_max_row_][_max_col_] ; inline void get_king_help( int crow, int ccol ) { int row_dis = king.row > crow ? king.row - crow : crow - king.row ; int col_dis = king.col > ccol ? king.col - ccol : ccol - king.col ; king_dis[crow][ccol] = row_dis < col_dis ? col_dis : row_dis ; } int get_cost( int crow, int ccol ) { int total = 0 ; for( int i=0; i<n_knight; i++ ){ int cur=min_dis[knights[i].row][knights[i].col][crow][ccol] ; if( cur==-1 ) return -1 ; total += cur ; } int king_cost = king_dis[crow][ccol] ; for( int ir=max(0,king.row-2); ir<min(n_row,king.row+3); ir++ ) for( int ic=max(0,king.col-2); ic<min(n_col,king.col+3); ic++ ){ if( min_dis[ir][ic][crow][ccol]==-1 ) continue ; int help_dis=0x7fffffff ; for( int who=0; who<n_knight; who++ ){ int kr=knights[who].row, kc=knights[who].col ; if( min_dis[kr][kc][ir][ic]==-1 || min_dis[kr][kc][crow][ccol]==-1 ) continue ; int cur_cost = min_dis[ir][ic][crow][ccol] + min_dis[kr][kc][ir][ic] + king_dis[ir][ic] - min_dis[kr][kc][crow][ccol] ; if( cur_cost < king_cost ) king_cost = cur_cost ; } } return total+king_cost ; } int main() { freopen("camelot.in", "r", stdin); freopen("camelot.out", "w", stdout); char row_char ; cin >> n_col >> n_row >> row_char >> king.col ; king.row = row_char - 'A' , --king.col ; for( n_knight=0; cin >> row_char >> knights[n_knight].col ; n_knight++ ) knights[n_knight].row = row_char -'A' , --knights[n_knight].col; for( int ir=0; ir<n_row; ir++ ) for( int ic=0; ic<n_col; ic++ ) get_min_dis( ir, ic ); for( int ir=0; ir<n_row; ir++ ) for( int ic=0; ic<n_col; ic++ ) get_king_help( ir, ic ); int min_cost = 0x7fffffff ; for( int ir=0; ir<n_row; ir++ ){ for( int ic=0; ic<n_col; ic++ ){ int ccost = get_cost( ir, ic ) ; if( ccost != -1 ) min_cost = ccost<min_cost ? ccost : min_cost ; } } cout << min_cost << endl ; return 0 ; }
发表评论
-
USACO Training Section 4.2 Cowcycles
2010-01-31 21:11 882英文原题 中文题译 ... -
USACO Training Section 4.2 Job Processing
2010-01-30 17:31 1130英文原题 中文题译 大意: 有N个工件,每个工件要经 ... -
USACO Training Section 4.2 Drainage Ditches ISAP非递归和多路增广递归
2010-01-29 19:39 1843郁闷。不小心覆盖了重 ... -
USACO Training Section 4.2 The Perfect Stall 匈牙利算法的递归和非递归实现
2010-01-28 21:21 1641英文原题 中文题译 ... -
USACO Training Section 4.1 Cryptcowgraphy 奶牛密码
2010-01-27 20:58 1195英文原题 中文题译 大意: 奶牛们要从农场逃跑 ... -
USACO Training Section 4.1 Beef McNuggets
2010-01-26 21:37 964英文原题 中文题译 大意: 给定N个正整数, ... -
USACO Training Section 4.1 Fence Loops
2010-01-24 20:14 1061英文原题 大意: 农夫布朗的牧场上的篱笆已经失 ... -
USACO Training Section 3.4 Closed Fences
2010-01-23 17:50 1400英文原题 题意 一个 ... -
USACO Training Section 3.4 American Heritage
2010-01-21 23:19 771英文原题 大意:有一个由最多26个大写字母构成的二叉树 ... -
USACO Training Section 3.4 Raucous Rockers
2010-01-21 23:09 795英文原题 大意:有S首歌,要放到D个CD里。每首歌有一个 ... -
USACO Training Section 3.4 Electric Fence
2010-01-21 12:57 967英文原题 大意:给定一个三角形(0,0),(m,n),( ... -
USACO Training Section 3.3 Riding the Fences
2010-01-20 23:38 1203英文原题 中文题译 经典的求欧拉路径:给定最多两个奇 ... -
USACO Training Section 3.3 Shopping Offers
2010-01-19 22:18 912英文原题 中文题译 这是个与日常生活相关的题。商场促销 ... -
USACO Training Section 3.3 A Game
2010-01-19 20:54 1091英文原题 有如下一个双人游戏:N(2 <= N & ... -
USACO Training Section 3.3 Home on the Range
2010-01-19 19:36 771英文原题 中文题译 大意:给定一个01矩阵,计算其中全为 ... -
USACO Training Section 3.2 Sweet Butter
2010-01-19 00:10 1043英文原题 中文题译 大意:农场之间有路构成稀疏无向图,若 ... -
USACO Training Section 3.2 Magic Squares
2010-01-18 23:11 928英文原题 中文题译 大意:有人发明了一种有8个块三种变换 ... -
USACO Training Section 3.2 Feed Ratios
2010-01-18 20:52 1304英文原题 中文题译 大意:给出整数a[i][j]和 ... -
USACO Training Section 3.2 Spinning Wheels
2010-01-18 19:37 866英文原题 中文题译 大意:有五个纺车飞轮,每个都有最多五 ... -
USACO Training Section 3.2 Stringsobits
2010-01-18 01:04 987英文原题 中文题译 大意:求至多有L个1的第i个N位二进 ...
相关推荐
ACM----USACO Training(解题博客网),提供了USACO Training解题的代码,可以参考一下
自己写的usaco_training带代码。供参考,有一道题是cheat的。自己看吧。
usaco测试数据+标程 usaco的section1到section5的所有测试数据 以及标准程序
usaco解题报告,就是usaco.training.gateway上面的题目全解
USACO题解+代码+翻译,好东西,超级齐全,对大家帮助不小,特别是现在nocow挂了
usaco section2.3--section5.5源程序。。。。。。。。。。。。。。。。
[USACO 1.1.4]破碎的项链.cpp
3.3 Section 3.3 3.4 Section 3.4 4 Chapter4 4.1 Section 4.1 4.2 Section 4.2 4.3 Section 4.3 4.4 Section 4.4 5 Chapter5 5.1 Section 5.1 5.2 Section 5.2 5.3 Section 5.3 5.4 Section 5.4 5.5 Section 5.5
USACO全部译题 USACO Training Program Gateway
USACO_培训USACO_培训Ride.java-> Gift1.java->
第一行 优惠商品的种类数(0 ) 第二行..第 s+1 行 每一行都用几个整数来表示一种优惠方式 第一个整数 n 第一行: 两个用空格隔开的
USACO training 教程翻译合集(清晰明确)
USACO培训页面美国计算机奥林匹克训练页2015年6月17日开始
One of the answer of the USACO training exercises.
usaco 合集,包括英文原题和中文译题,测试数据以及答案,很全啊!usaco 合集usaco 合集usaco 合集usaco 合集
usaco历年测试数据
usaco 2010-2011 nov news,喜欢usaco的朋友可以看看
USACO题集及答案
某些USACO题目的答案,很详细,代码清晰结构良好,算法高效易于调试
usaco的总结和心得 包括了对题目的分了和总结 以及对题目的解法概括