[USACO3.3.3]camelot

  题目传送门:http://www.nocow.cn/index.php/Translate:USACO/camelot

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

  题解传送门:http://www.nocow.cn/index.php/USACO/camelot

  

/*
ID:abc31261
LANG:C++
TASK:camelot
*/

#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
const int maxn=33,maxm=800;
int n,m,ans=100000000,flag[maxn][maxn],f1[2][maxn][maxn][maxn][maxn],f[maxn][maxn],num=-1,numx[maxm],numy[maxm],knx[]={0,-2,-2,-1,-1,1,1,2,2},kny[]={0,-1,1,-2,2,-2,2,-1,1},
                                                ky[]={0,-1,0,1,-1,1,-1,0,1},kx[]={0,-1,-1,-1,0,0,1,1,1};

void read()
{
    char in[5];
    scanf("%d%d",&n,&m);
    while (scanf("%s%d",in,&numx[++num])==2)numy[num]=in[0]-‘A‘+1;
    num--;
}

bool check(int x,int y)
{
    if (x<=n && x>0 && y<=m && y>0)return true;
    return false;
}

void bfs(int a,int b,int c)
{
    queue<int> qx,qy;
    qx.push(a),qy.push(b);
    memset(flag,true,sizeof(flag));
    flag[a][b]=false;
    f1[c][a][b][a][b]=0;
    while (!qx.empty())
    {
        int x=qx.front(),y=qy.front();qx.pop(),qy.pop();
        for (int i=1;i<=8;i++)
        {
            int x1=x+knx[i],y1=y+kny[i];
            if (c==1)x1=x+kx[i],y1=y+ky[i];
            if (check(x1,y1) && flag[x1][y1])
            {
                qx.push(x1),qy.push(y1);
                flag[x1][y1]=false;
                f1[c][a][b][x1][y1]=f1[c][a][b][x][y]+1;
            }
        }
    }
}

void solve()
{
    int q,i,j,l,k;
    for (i=1;i<=n;i++)
        for (j=1;j<=m;j++)
        {
            f[i][j]+=f1[1][numx[0]][numy[0]][i][j];
            ans=min(ans,f[i][j]);
        }
    for (q=1;q<=num;q++)
        for (i=1;i<=n;i++)
            for (j=1;j<=m;j++)
                 for (l=numx[0]-2;l<=numx[0]+2;l++)
                     for (k=numy[0]-2;k<=numy[0]+2;k++)
                         if (l>0 && l<=n && k>0 && k<=m)
                           ans=min(f1[1][numx[0]][numy[0]][l][k]+f1[0][numx[q]][numy[q]][l][k]+f1[0][l][k][i][j]+f[i][j]-f1[0][numx[q]][numy[q]][i][j]-f1[1][numx[0]][numy[0]][i][j],ans);

}
int main()
{
    int i,j,l;
    freopen("camelot.in","r",stdin);
    freopen("camelot.out","w",stdout);
    read();
    memset(f,0,sizeof(f));
    memset(f1,0x2f,sizeof(f1));
    bfs(numx[0],numy[0],1);
    for (i=1;i<=n;i++)
        for (j=1;j<=m;j++)bfs(i,j,0);
    for (i=1;i<=num;i++)
        for (j=1;j<=n;j++)
            for (l=1;l<=m;l++)
            f[j][l]+=f1[0][numx[i]][numy[i]][j][l];
    solve();
    cout<<ans<<endl;
    return 0;
}
时间: 2025-01-06 10:18:30

[USACO3.3.3]camelot的相关文章

洛谷P1930 亚瑟王的宫殿 Camelot

P1930 亚瑟王的宫殿 Camelot 19通过 53提交 题目提供者JOHNKRAM 标签USACO 难度提高+/省选- 提交  讨论  题解 最新讨论 暂时没有讨论 题目描述 很久以前,亚瑟王和他的骑士习惯每年元旦去庆祝他们的友谊.为了纪念上述事件, 我们把这些故事看作是一个棋盘游戏.有一个国王和若干个骑士被放置在一个由许多方格 组成的棋盘上,没有两个骑士在同一个方格内. 这个例子是标准的 8*8 棋盘 国王可以移动到任何一个相邻的方格,从下图中黑子位置到下图中白子位置前提是他 不掉出棋盘

usaco-3.1-PROB Shaping Regions-漂浮法

漂浮法,顾名思义,就是一块块的往上飘. 以逆序来进行放置,即n to 1.逆序的好处在于放置一个矩形后,俯视看到的就是最终俯视该矩形应该看到的.因为挡着它的矩形在之前已经放置好了,所以可直接统计,为递归创造了条件.每放一个矩形,可以想象成将其扔入一密度很大的海水底部,海分成了n层,然后矩形开始向上浮.在上浮过程中若碰撞到其他的矩形则断裂成几个小矩形,继续上浮,直到浮出水面.于是想到用个递归来模拟上浮过程. /* ID: rowanha3 LANG: C++ TASK: rect1 */ #inc

USACO 3.3 Camelot

CamelotIOI 98 Centuries ago, King Arthur and the Knights of the Round Table used to meet every year on New Year's Day to celebrate their fellowship. In remembrance of these events, we consider a board game for one player, on which one chesspiece king

usaco Camelot

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

USACO camelot 好题

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

[usaco3.2.3]spin

这道题直接枚举就好了,但我当时竟然没想到,我真是太失败了.....Q_Q /* ID:abc31261 LANG:C++ TASK:spin */ #include<cstdio> #include<cstring> #include<iostream> using namespace std; const int n=5,maxn=360; int s[10],first[10][10],end[10][10],num[10],f[maxn*2]; bool flag

[usaco3.2.5]msquare

题目传送门:http://www.nocow.cn/index.php/Translate:USACO/msquare 这道题bfs+hash,但想到要判重的数字不多,就直接用了map,数组传递有些麻烦,所以直接写在了一起,会有点乱 /* ID:abc31261 LANG:C++ TASK:msquare */ #include<cstdio> #include<cstring> #include<queue> #include<map> #include&

USACO--3.2Sweet Butter+推优化的Dijkstral算法

这个题目思路是很简单的,我们只需要枚举每个顶点作为目的地,然后再取其中距离总和最小的作为答案.开始的时候我用的是floyd一次就将所有点之间的最小距离求出来,但是超时了. 后面每次枚举一个点就用堆优化的dijkstral求一次这个点到其余点的最短路,这样就可以过了.算法中还用数组模拟了图的邻接矩阵. 代码如下: /* ID: 15674811 LANG: C++ TASK: butter */ #include<iostream> #include<cstdio> #include

usaco-3.4-rockers-passed

又是一个背包问题,动态规划求解: /* ID: qq104801 LANG: C++ TASK: rockers */ #include <iostream> #include <fstream> #include <cstring> #include <vector> #include <queue> #include <stack> #include <algorithm> using namespace std; #