zoukankan      html  css  js  c++  java
  • USACO camelot 好题

      这道题的意思是地图上有一些骑士和一个国王, 骑士和国王要在一点会和,你可以选择一个骑士和国王在一点会和然后骑士会带着国王继续走, 问他们汇合的最少步数和是多少?考虑一个骑士当没有国王的时候可以很容易的求出他到每个点的最短路径a, 现在他要带着国王, 那么我们可以计算出他带着国王到某一点的最短路径b, 那么为了接国王他多走的路就是b - a,这下我们可以维护两个数组, cost[i][j]表示所有骑士不接国王到达i, j所需要的最短的步数, kcost[i][j]表示有一个骑士接国王到i,j,骑士多走的步数(也包括国王走的步数),那么答案就是min(cost[i][j]+kcost[i][j]),代码如下:

    /*
        ID: m1500293
        LANG: C++
        PROG: camelot
    */
    
    
    
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    int N, M;
    int kx, ky;
    
    int cost[35][35], kingcost[35][35];
    int kcost[35][35];
    int dis[35][35][2];
    
    int dx[] = {-2, -2, -1, -1, +1, +1, +2, +2};
    int dy[] = {-1, +1, -2, +2, -2, +2, -1, +1};
    bool inside(int x, int y) { return (x>=0&&x<N&&y>=0&&y<M); }
    
    struct State
    {
        int x, y, flog;
        State() {}
        State(int x, int y, int flog):x(x), y(y), flog(flog) {}
    };
    int inque[35][35][2];
    void bfs(int knx, int kny)
    {
        memset(inque, 0, sizeof(inque));
        memset(dis, 0x3f, sizeof(dis));
        queue<State> que;
        dis[knx][kny][0] = 0;
        inque[knx][kny][0] = 1;
        que.push(State(knx, kny, 0));
        while(!que.empty())
        {
            State u = que.front(); que.pop();
            inque[u.x][u.y][u.flog] = 0;
            int udis = dis[u.x][u.y][u.flog];
            for(int i=0; i<8; i++)
            {
                int nx = u.x+dx[i], ny = u.y+dy[i];
                if(!inside(nx, ny)) continue;
                if(dis[nx][ny][u.flog] > udis + 1)
                {
                    dis[nx][ny][u.flog] = udis+1;
                    if(!inque[nx][ny][u.flog])
                    {
                        inque[nx][ny][u.flog] = 1;
                        que.push(State(nx, ny, u.flog));
                    }
                }
            }
            if(!u.flog && dis[u.x][u.y][1]>udis + kingcost[u.x][u.y])
            {
                dis[u.x][u.y][1] = udis+kingcost[u.x][u.y];
                if(!inque[u.x][u.y][1])
                {
                    inque[u.x][u.y][1] = 1;
                    que.push(State(u.x, u.y, 1));
                }
            }
        }
    }
    
    int main()
    {
        freopen("camelot.in", "r", stdin);
        freopen("camelot.out", "w", stdout);
        scanf("%d%d", &M, &N);
        char tp[5]; int tpy;
        scanf("%s%d", tp, &tpy);
        kx = tp[0]-'A'; ky = tpy - 1;
        for(int i=0; i<N; i++)
        for(int j=0; j<M; j++)
           kcost[i][j] = kingcost[i][j] = max(abs(i-kx), abs(j-ky));
        memset(cost, 0, sizeof(cost));
        while(scanf("%s%d", tp, &tpy) == 2)
        {
            int knx = tp[0]-'A', kny = tpy - 1;
            bfs(knx, kny);
            for(int i=0; i<N; i++)
                for(int j=0; j<M; j++)
                {
                    if(dis[i][j][0] == 0x3f3f3f3f)                //骑士不可能到达这一点的情况
                    {
                        cost[i][j] = 0x3f3f3f3f;
                        continue;
                    }
                    cost[i][j] += dis[i][j][0];
                    kcost[i][j] = min(kcost[i][j], dis[i][j][1]-dis[i][j][0]);
                }
        }
        int res = 0x3fffffff;
        for(int i=0; i<N; i++)
            for(int j=0; j<M; j++)
            {
                res = min(res, cost[i][j]+kcost[i][j]);
            }
        printf("%d
    ", res);
        return 0;
    }
  • 相关阅读:
    项目相关的风险要素及分类
    IT从业人员必看的10个论坛(转)
    Android Input设备debug技巧
    Android中如何判断是否联网
    paip.tree 生成目录树到txt后的折叠查看
    hdu 4737 A Bit Fun
    FLASH ROM与EEPROM的区别
    Robot Framework学习路线
    Distinguishing Between Embedded and General-Purpose Computing
    服务的生命周期
  • 原文地址:https://www.cnblogs.com/xingxing1024/p/5096564.html
Copyright © 2011-2022 走看看