USACO 3.3.3 Camelot解题报告
这题本来是个很水的题,但是USACO的特点大家是知道的:细节折磨死你……这题也不例外,好想其实也挺好写。但是如果不是一把成就会很悲剧……还好我是幸运的,基本一会就过了……
但是这个题还是碰到了相当的问题,就是说pascal当中有我们无敌的神器fillword和filldword。但是C++当中只有一个fill,这个东西还要算指针头和指针尾,着实很悲剧。所以逼得我不得不用memset,很悲剧的是这个题初始这个最大值不能太大,因为有一个加的步骤,如果太大,就会造成各种负数的惨剧。。而memset本质上和fillchar是一样的,而他们在把一个数组同意赋值成一个大数的时候,这个大数往往是不能有太多的变化的。。
经历了各种实验,最后定下来用0xF,这个数吧,说实话我看着都觉得诡异……因为实际上是(0000 1111 0000 1111)2,而这个数把实际上是(3855)10。怎么样,够诡异吧……所以希望找到一位懂fill的大神给偶讲讲fill具体的用法。
另外终于体会到了用流来读入真的是异常的NB,解决了一堆不必要的麻烦,也不用处理字符串拆空格了,一个cin全部解决~
代码:
/* TASK:camelot LANG:C++ */ #include <iostream> #include <fstream> #include <cstring> #include <climits> using namespace std; class point { public: int x,y; }; const int dx[8] = {1,1,2,2,-1,-1,-2,-2}; const int dy[8] = {2,-2,1,-1,2,-2,1,-1}; const int kx[8] = {1,1,1,-1,-1,-1,0,0}; const int ky[8] = {-1,0,1,-1,0,1,-1,1}; int n, m, best, tot, tot2; point situ[902], kingSitu[902]; int dis[31][31][31][31], sum[31][31], disKing[31][31]; bool vis[31][31]; point q[902]; void init() { scanf("%d%d", &n, &m); char ch; int x; while (cin >>ch >>x) { situ[tot].y = ch - 'A' + 1; situ[tot++].x = x; } } void bfs(int x, int y) { memset(vis, 0, sizeof(vis)); int front = 1, rear = 1; dis[x][y][x][y] = 0; vis[x][y] = 1; q[front].x = x; q[front].y = y; while (front <= rear) { for (int i = 0; i < 8; i++) { int tx = q[front].x + dx[i]; int ty = q[front].y + dy[i]; if (tx >= 1 && ty >= 1 && tx <=n && ty <=m && !vis[tx][ty]) { q[++rear].x = tx; q[rear].y = ty; vis[tx][ty] = 1; dis[x][y][tx][ty] = dis[x][y][q[front].x][q[front].y] + 1; } } front++; } } void bfsKing() { int x = situ[0].x, y = situ[0].y; memset(vis, 0, sizeof(vis)); int front = 1, rear = 1; disKing[x][y] = 0; vis[x][y] = 1; q[front].x = x; q[front].y = y; while (front <= rear) { for (int i = 0; i < 8; i++) { int tx = q[front].x + kx[i]; int ty = q[front].y + ky[i]; if (tx >= 1 && ty >= 1 && tx <=n && ty <=m && !vis[tx][ty]) { q[++rear].x = tx; q[rear].y = ty; vis[tx][ty] = 1; disKing[tx][ty] = disKing[q[front].x][q[front].y] + 1; } } front++; } } void solve() { memset(dis, 0xF, sizeof(dis)); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) bfs(i,j); memset(disKing, 0xF, sizeof(disKing)); bfsKing(); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) for (int k = 1; k < tot; k++) sum[i][j] += dis[situ[k].x][situ[k].y][i][j]; for (int i = -2; i <= 2; i++) for (int j = -2; j <= 2; j++) if (situ[0].x + i >= 1 && situ[0].y + j >= 1 && situ[0].x + i <= n && situ[0].y + j <=m) { kingSitu[tot2].x = situ[0].x + i; kingSitu[tot2++].y = situ[0].y + j; } best = INT_MAX / 2; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) best = min(best, sum[i][j] + disKing[i][j]); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) for (int k = 1; k < tot; k++) for (int t = 0; t < tot2; t++) best = min(best, sum[i][j] - dis[i][j][situ[k].x][situ[k].y] +dis[situ[k].x][situ[k].y][kingSitu[t].x][kingSitu[t].y] +dis[kingSitu[t].x][kingSitu[t].y][i][j]+disKing[kingSitu[t].x][kingSitu[t].y]); } void print() { printf("%d\n", best); } int main() { freopen("camelot.in", "r", stdin); freopen("camelot.out", "w", stdout); init(); solve(); print(); return 0; }