码迷,mamicode.com
首页 > 其他好文 > 详细

usaco Camelot

时间:2015-09-23 20:58:31      阅读:230      评论:0      收藏:0      [点我收藏+]

标签:

题意是,国王和很多骑士在棋盘的不同位置,国王要和骑士在一点聚集。

若某个骑士和国王相遇之后,骑士和国王共同走一步,只算一步。等于是骑士背上了国王,国王不再走路。

第一遍我的算法用BFS计算出了每个骑士到棋盘上每个位置的最短距离。枚举每个点作为集合点,然后判断骑士能否在走到集合点的过程中遇上国王。依据是,国王所在点在骑士要到达的距离小于集合点,这么做其实并不能保证骑士遇见了国王,但还是骗过了5个测试点。

后来看别人才知道是国王在走两步只内就能遇见骑士。关于证明我没找到。

/*
ID: modengd1
PROG: camelot
LANG: C++
*/
#include <iostream>
#include <stdio.h>
#include <memory.h>
#include <queue>
#include <vector>
#include <algorithm>
#define MofInt 0x7fffffff
using namespace std;
int R,C;
int step[27][31][27][31];
int kingstep[27][31];
int dx[8]={1,1,-1,-1,2,2,-2,-2};
int dy[8]={2,-2,2,-2,1,-1,1,-1};
int dxk[8]={0,0,1,1,1,-1,-1,-1};
int dyk[8]={1,-1,0,1,-1,0,1,-1};
typedef pair<int,int> position;
vector<position> PoS;
position king;
struct node
{
    int x,y,step;
    node(int xx,int yy,int ss)
    {
        x=xx;y=yy;step=ss;
    }
    node(){}
};
void BFSforking()
{
    memset(kingstep,0x7f,sizeof(kingstep));
    queue<node> Q;
    Q.push(node(king.first,king.second,0));//起始点
    kingstep[king.first][king.second]=0;
    while(!Q.empty())
    {
        node now=Q.front();
        Q.pop();
        for(int j=0;j<8;j++)
        {
            node next=node(now.x+dxk[j],now.y+dyk[j],now.step+1);
            if(next.x<1||next.x>R||next.y<1||next.y>C)
                continue;
            if(kingstep[next.x][next.y]<=next.step)
                continue;
            kingstep[next.x][next.y]=next.step;
            Q.push(next);
        }
    }
}
void BFS()
{
    for(int i=1;i<=R;i++)
    {
        for(int k=1;k<=C;k++)
        {
            memset(step[i][k],0x7f,sizeof(step[i][k]));
            queue<node> Q;
            Q.push(node(i,k,0));//起始点
            step[i][k][i][k]=0;
            while(!Q.empty())
            {
                node now=Q.front();
                Q.pop();
                for(int j=0;j<8;j++)
                {
                    node next=node(now.x+dx[j],now.y+dy[j],now.step+1);
                    if(next.x<1||next.x>R||next.y<1||next.y>C)
                        continue;
                    if(step[i][k][next.x][next.y]<=next.step)
                        continue;
                    step[i][k][next.x][next.y]=next.step;
                    Q.push(next);
                }
            }
        }
    }
}
void output()
{
    if(PoS.size()==0)
    {
        cout<<0<<endl;
        return;
    }
    //计算king到所有骑士当中最近的一个的距离
    int ans=MofInt;

    //枚举集合点

    for(int i=1;i<=R;i++)
    {
        for(int j=1;j<=C;j++)
        {
            bool isa=true;
            //不接国王
            int temp=0;
            for(int k=0;k<PoS.size();k++)//加上每个骑士走到这点所需的距离
            {
                if(step[i][j][PoS[k].first][PoS[k].second]==2139062143)
                    isa=false;
                temp+=step[i][j][PoS[k].first][PoS[k].second];
            }
            temp+=kingstep[i][j];
            if(!isa)
                break;
            int temp2=MofInt;
            //接上国王

            int other;
            int spetialone;
            for(int k=0;k<PoS.size();k++)//枚举哪个骑士接国王
            {
                other=temp-step[i][j][PoS[k].first][PoS[k].second]-kingstep[i][j];;
                //在哪接

                for(int l=max(1,king.first-2);l<=min(R,king.first+2);l++)
                {
                    for(int p=max(1,king.second-2);p<=min(C,king.second+2);p++)
                    {
                        if(kingstep[l][p]==2139062143||step[i][j][l][p]==2139062143||step[l][p][PoS[k].first][PoS[k].second]==2139062143)
                            break;
                        spetialone=step[i][j][l][p]+step[l][p][PoS[k].first][PoS[k].second]+kingstep[l][p];
                        temp2=min(temp2,spetialone+other);
                    }
                }
            }
            temp=min(temp,temp2);
            ans=min(ans,temp);//和国王直接走到集合点作比较
        }
    }
    if(ans==MofInt&&PoS.size()==1)//如果骑士寸步难行,且只有一个骑士
    {
        ans=kingstep[PoS[0].first][PoS[0].second];
    }
    cout<<ans<<endl;
}
int main()
{
    freopen("camelot.in","r",stdin);
    freopen("camelot.out","w",stdout);
    scanf("%d%d",&C,&R);
    int b;char a;
    PoS.clear();
    getchar();
    scanf("%c %d",&a,&b);
    king.first=a-‘A‘+1;king.second=b;
    getchar();
    while(~scanf("%c %d",&a,&b))
    {
        PoS.push_back(position(a-‘A‘+1,b));
        getchar();
    }
    BFSforking();
    BFS();
    output();
    return 0;
}

  

usaco Camelot

标签:

原文地址:http://www.cnblogs.com/modengdubai/p/4833444.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!