USACO 3.3 Camelot
2013-01-11 00:10
260 查看
题意:
在R行C列的棋盘上(R<=30,C<=26),有互相不重叠的若干个骑士和王,骑士可以按照马的方式走,王可以走周围的八个位置。
骑士和王到达一个点的时候骑士可以接王。
问:最少经过多少步能够让所有的棋子到达同一格。
思路:
首先棋盘的每两点之间的骑士最短距离可以通过R*C次BFS得到。
考虑暴力枚举:
for 集合点(R*C)
for 接王的骑士(R*C)
for 接王的点(R*C)
算出距离
这样,复杂度达到了O((R*C)^3),必然超时,于是想方设法进行剪枝。
考虑以下几种剪枝方式:(无证明。。。来自From北极星天南)
1)由于王总是比骑士走得慢,所以接王的点一定靠近王(在王的某个范围内)。
2)在枚举集合点的时候,如果所有的骑士到达该点的距离和已经大于当前答案,那么不许进行后面的枚举
3)当骑士较多时,集合点在骑士们的中心附近(骑士均值坐标的某个范围内)。
注意:
交了很多次才过。
1)读入数据的时候,纵坐标可能是两位的数字,不是单个字符,但是横坐标就是单个字符
2)x对应的是column,y对应的是row
3)可能存在不能到达的两个点,所以所有的dist[][][][]要初始化为INF而不是0
4)王一步可以到达周围八个点,所以当王从a,b 到c,d 的最小步数是max(abs(a,b),abs(c-d))
5)只有一个王单独处理,答案是0
代码:
在R行C列的棋盘上(R<=30,C<=26),有互相不重叠的若干个骑士和王,骑士可以按照马的方式走,王可以走周围的八个位置。
骑士和王到达一个点的时候骑士可以接王。
问:最少经过多少步能够让所有的棋子到达同一格。
思路:
首先棋盘的每两点之间的骑士最短距离可以通过R*C次BFS得到。
考虑暴力枚举:
for 集合点(R*C)
for 接王的骑士(R*C)
for 接王的点(R*C)
算出距离
这样,复杂度达到了O((R*C)^3),必然超时,于是想方设法进行剪枝。
考虑以下几种剪枝方式:(无证明。。。来自From北极星天南)
1)由于王总是比骑士走得慢,所以接王的点一定靠近王(在王的某个范围内)。
2)在枚举集合点的时候,如果所有的骑士到达该点的距离和已经大于当前答案,那么不许进行后面的枚举
3)当骑士较多时,集合点在骑士们的中心附近(骑士均值坐标的某个范围内)。
注意:
交了很多次才过。
1)读入数据的时候,纵坐标可能是两位的数字,不是单个字符,但是横坐标就是单个字符
2)x对应的是column,y对应的是row
3)可能存在不能到达的两个点,所以所有的dist[][][][]要初始化为INF而不是0
4)王一步可以到达周围八个点,所以当王从a,b 到c,d 的最小步数是max(abs(a,b),abs(c-d))
5)只有一个王单独处理,答案是0
Executing... Test 1: TEST OK [0.000 secs, 7476 KB] Test 2: TEST OK [0.000 secs, 7476 KB] Test 3: TEST OK [0.000 secs, 7476 KB] Test 4: TEST OK [0.011 secs, 7476 KB] Test 5: TEST OK [0.065 secs, 7476 KB] Test 6: TEST OK [0.065 secs, 7476 KB] Test 7: TEST OK [0.000 secs, 7476 KB] Test 8: TEST OK [0.011 secs, 7476 KB] Test 9: TEST OK [0.032 secs, 7476 KB] Test 10: TEST OK [0.065 secs, 7476 KB] Test 11: TEST OK [0.000 secs, 7476 KB] Test 12: TEST OK [0.000 secs, 7476 KB] Test 13: TEST OK [0.000 secs, 7476 KB] Test 14: TEST OK [0.000 secs, 7476 KB] Test 15: TEST OK [0.000 secs, 7476 KB] Test 16: TEST OK [0.000 secs, 7476 KB] Test 17: TEST OK [0.000 secs, 7476 KB] Test 18: TEST OK [0.000 secs, 7476 KB] Test 19: TEST OK [0.000 secs, 7476 KB] Test 20: TEST OK [0.000 secs, 7476 KB]
代码:
/* ID: jasison2 LANG: C++ TASK: camelot */ #include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; #define N 32 #define INF 0x7fffffff #define MAX(a,b) (a)<(b)?(b):(a) #define MIN(a,b) (a)<(b)?(a):(b) inline int ABS(int x) { return x<0 ? -x : x; } int r, c, n; int dist ; // distance with knight bool vis ; int p[N*N][2]; // king and knight position int dx, dy; // gather position int dir[8][2] = {{-2,-1},{-2,1},{-1,-2},{-1,2},{1,2},{1,-2},{2,-1},{2,1}}; struct Point { int x, y; Point() {} Point(int _x, int _y): x(_x), y(_y){} bool legal() { return x>0 && x<=c && y>0 && y<=r && !vis[x][y]; } void visit() { vis[x][y] = true; } }; inline void input() { cin >> r >> c; n = 0; char x; dx = dy = 0; while (cin >> x >> p [1]) { p [0] = x - 'A' + 1; if (n) { dx += p [0]; dy += p [1]; } n ++; } if (n > 1) { dx /= (n-1); dy /= (n-1); } } void bfs() { Point cur, nxt; for (int i = 1; i <= c; ++ i) { for (int j = 1; j <= r; ++ j) { for (int ix = 1; ix <= c; ++ ix) for (int iy = 1; iy <= r; ++ iy) dist[i][j][ix][iy] = 100; memset(vis, false, sizeof(vis)); queue <Point> Q; Q.push(Point(i,j)); vis[i][j] = true; dist[i][j][i][j] = 0; while (!Q.empty()) { cur = Q.front(); Q.pop(); for (int k = 0; k < 8; ++ k) { nxt = Point(cur.x+dir[k][0], cur.y+dir[k][1]); if (nxt.legal()) { dist[i][j][nxt.x][nxt.y] = dist[i][j][cur.x][cur.y] + 1; nxt.visit(); Q.push(nxt); } } } } } } int calc() { if (n == 1) return 0; int ans = INF; int sdx, sdy, edx, edy, sx, sy, ex, ey; if (n < 3) { sdx = sdy = 1; edx = c; edy = r; } else { sdx = MAX(1,dx-2); sdy = MAX(1,dy-2); edx = MIN(c,dx+2); edy = MIN(r,dy+2); } sx = MAX(1,p[0][0]-2); sy = MAX(1,p[0][1]-2); ex = MIN(c,p[0][0]+2); ey = MIN(r,p[0][1]+2); for (dx = sdx; dx <= edx; ++ dx) { for (dy = sdy; dy <= edy; ++ dy) { int tans = 0; for (int k = 1; k < n; ++ k) tans += dist[p[k][0]][p[k][1]][dx][dy]; if (tans > ans) continue; for (int k = 1; k < n; ++ k) { tans -= dist[p[k][0]][p[k][1]][dx][dy]; for (int x = sx; x <= ex; ++ x) { for (int y = sy; y <= ey; ++ y) { tans += dist[p[k][0]][p[k][1]][x][y] + dist[x][y][dx][dy]; tans += MAX(ABS(x-p[0][0]), ABS(y-p[0][1])); if (tans < ans) ans = tans; tans -= dist[p[k][0]][p[k][1]][x][y] + dist[x][y][dx][dy]; tans -= MAX(ABS(x-p[0][0]), ABS(y-p[0][1])); } } tans += dist[p[k][0]][p[k][1]][dx][dy]; } } } return ans; } void output() { printf("%d\n", calc()); } int main() { freopen("camelot.in","r",stdin); freopen("camelot.out","w",stdout); input(); bfs(); output(); }
相关文章推荐
- USACO-Section3.3 Camelot【宽度优先搜索】
- USACO 3.3 Camelot
- usaco-3.3-camelot-passed
- USACO 3.3 Camelot (camelot)
- Camelot USACO 3.3(阵亡)
- USACO Section 3.3 Camelot
- USACO Section 3.3 Camelot(搜索)
- USACO 3.3 Camelot(BFS+乱搞)
- USACO Section 3.3 Camelot - 略恶心的BFS
- [USACO3.3]亚瑟王的宫殿 Camelot
- USACO-Section 3.3 Camelot (最短路&&枚举)
- A Game USACO 3.3 (DP阵亡)
- usaco 3.3 range 2008.11.7
- Home On The Range_usaco3.3_dp
- USACO 3.3 Shopping Offers
- USACO Section 3.3 A Game(dp)
- USACO 3.3 Riding the Fences(欧拉路输出路径)
- USACO section Camelot(枚举+队列优化)
- usaco Camelot
- USACO-Section 3.3-PROB Shopping Offers