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;
}
posted @ 2011-05-23 20:55  Skyprophet  阅读(732)  评论(0编辑  收藏  举报