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\n", res);
    return 0;
}
时间: 2024-12-24 20:24:17

USACO camelot 好题的相关文章

usaco Camelot

题意是,国王和很多骑士在棋盘的不同位置,国王要和骑士在一点聚集. 若某个骑士和国王相遇之后,骑士和国王共同走一步,只算一步.等于是骑士背上了国王,国王不再走路. 第一遍我的算法用BFS计算出了每个骑士到棋盘上每个位置的最短距离.枚举每个点作为集合点,然后判断骑士能否在走到集合点的过程中遇上国王.依据是,国王所在点在骑士要到达的距离小于集合点,这么做其实并不能保证骑士遇见了国王,但还是骗过了5个测试点. 后来看别人才知道是国王在走两步只内就能遇见骑士.关于证明我没找到. /* ID: modeng

[题解]某模拟题(USACO月赛部分题+noip2005部分题)

题目描述 农场上有N(1 <= N <= 50,000)堆草,放在不同的地点上.FJ有一辆拖拉机,也在农场上.拖拉机和草堆都表示为二维平面上的整数坐标,坐标值在1..1000的范围内.拖拉机的初始位置与所有草堆不同. FJ开拖拉机时,只能平行于坐标轴(即东.南.西.北四个方向),而且每次开动的一段必须是整数长度.例如,他可以向北开2个单位长度,然后向东开3个单位长度.拖拉机不能开到草堆的位置. 请帮助FJ计算出最少要移动多少个草堆,他才能将拖拉机开回坐标原点. 拖拉机可以开到1..1000之外

[USACO3.3.3]camelot

题目传送门:http://www.nocow.cn/index.php/Translate:USACO/camelot 这道题让我心痛,一开始写写不出,后来拖了很久,决定去看题解,没想到又看不懂官方题解,唉!后来看了下面的题解做了出来.题解的话,大概就是先预处理每个格子到另外格子的位置,再枚举在王的坐标+-2位置接王,枚举所有棋子的集中点加起来计算就好了.我的代码为了方便略粗鲁. 题解传送门:http://www.nocow.cn/index.php/USACO/camelot /* ID:ab

USACO 6.5 Checker Challenge

Checker Challenge Examine the 6x6 checkerboard below and note that the six checkers are arranged on the board so that one and only one is placed in each row and each column, and there is never more than one in any diagonal. (Diagonals run from southe

[USACO]控制公司 Controlling Companies

玄妙的搜索 题目描述 有些公司是其他公司的部分拥有者,因为他们获得了其他公司发行的股票的一部分.(此处略去一句废话)据说,如果至少满足了以下三个条件之一,公司A就可以控制公司B了: 公司A = 公司B. 公司A拥有大于50%的公司B的股票. 公司A控制K(K >= 1)个公司,记为C1, ..., CK,每个公司Ci拥有xi%的公司B的股票,并且x1+ .... + xK > 50%. 给你一个表,每行包括三个数(i,j,p):表明公司i享有公司j的p%的股票.计算所有的数对(h,s),表明公

1671: [Usaco2005 Dec]Knights of Ni 骑士

1671: [Usaco2005 Dec]Knights of Ni 骑士 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 254  Solved: 163[Submit][Status][Discuss] Description Bessie is in Camelot and has encountered a sticky situation: she needs to pass through the forest that is guarde

接下来的计划

做事得有目的性,否则容易迷失方向. 接下来最大的事就是NOIP了吧,我这种弱逼还在为noip担心...NOIP一定要AK!所以打算切掉BZOJ上的USACO的月赛题both Silver & Gold.为了不让这个东西影响NOIP之后的事,所以准备把暑假的flag给补掉.然后就是翱犇给我做的计划,其实这个才是最重要的. 所以按照重要性降序排出: 翱犇给我做的计划(一定要完成) 月赛题娱(cui)乐(can)身心(放松向(雾),不一定要每道题都码,想清楚了就拿@iwtwiioi的程序交233333

BZOJ1658 [Usaco2006 Mar]Water Slides 滑水

说好的一天题解来啦! 首先作为usaco的silver题,我被虐了...调了两天才搞定 最后发现是sort忘了+1(start + cnt1 (+ 1))还去问管理员要了数据,真是... 做法倒不是很难想: (1)把点分成出度>入度和入度>出度两种 (2)跑一遍网络流 好像会T的很惨...然后改进: 发现两条线段交叉一定没有不交叉来得好(就是简单地贪心思想) 于是两类点排序,直接一个一个配对答案一定是最小的. 1 /***************************************

[Usaco2007 Dec][BZOJ1690] 奶牛的旅行|分数规划|二分|SPFA

1690: [Usaco2007 Dec]奶牛的旅行 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 700  Solved: 363[Submit][Status][Discuss] Description 作为对奶牛们辛勤工作的回报,Farmer John决定带她们去附近的大城市玩一天.旅行的前夜,奶牛们在兴奋地讨论如何最好地享受这难得的闲暇. 很幸运地,奶牛们找到了一张详细的城市地图,上面标注了城市中所有L(2 <= L <= 1000)座标志