您的位置:首页 > 其它

usaco3.3.4亚瑟王的宫殿

2014-08-03 15:53 411 查看


一个万无一失的方法

对于骑士带王去会合的情况,枚举王的原位置和八个方向,也就是说王和骑士的汇合点相对于王的原位置为上下左右或者斜45度方向。

比如在8*8的棋盘上,王的位置用k表示,需要枚举的带王的点用1表示,其余点用0表示则有下图:
0 0 1 0 0 1 0 0
1 0 1 0 1 0 0 0
0 1 1 1 0 0 0 0
1 1 k 1 1 1 1 1
0 1 1 1 0 0 0 0
1 0 1 0 1 0 0 0
0 0 1 0 0 1 0 0
0 0 1 0 0 0 1 0


对于其他带王点的情况,总可以等效为以上情况之一,这样枚举不会超时。

需要注意的是,输入时的R,C分别代表列数和行数。

主要用bfs,搜出对于每一个knight到达每一个格子所需的步数。(调试了一个下午,结果是字母打错了,好想骂人啊)

具体思路看代码吧。

#include<cstdio>

#include<iostream>

#include <queue>

#include <cmath>

#include <algorithm>

using namespace std;

struct aaaa{int x,y,d;};

int moveking[8][2]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};

int moveknight[8][2]={{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1}};

int king[2],knight[1041][2],kingdist[27][41];

int disttoking[200][27][41];

int dist[1041][27][41],zonghe[27][41],R,C,numknight=1,num=0;

void bfs(int s[2],int move[8][2],int dist1[27][41]);

int main()

{

    //freopen("camelot.in","r",stdin);

    //freopen("camelot.out","w",stdout);

    cin>>C>>R;

    char a;

    cin>>a>>king[1];

    king[0]=a-64;

    while(cin>>a>>knight[numknight][1])

    {

        knight[numknight][0]=a-64;

        numknight++;

    }

    numknight--;

    bfs(king,moveking,kingdist);

    for(int i=0;i<8;i++)

    {

        int s[2];

        s[0]=king[0]+moveking[i][0];

        s[1]=king[1]+moveking[i][1];

        while(s[0]>0&&s[0]<=R&&s[1]>0&&s[1]<=C)

        {

            bfs(s,moveknight,disttoking[num++]);

            s[0]=s[0]+moveking[i][0];

            s[1]=s[1]+moveking[i][1];

        }

    }

    bfs(king,moveknight,disttoking[num]);

    for(int i=1;i<=numknight;i++)

    {

       bfs(knight[i],moveknight,dist[i]);

    }

    int min1=99999999,lala;

    for(int i=1;i<=R;i++)

        for(int j=1;j<=C;j++)

        for(int k=1;k<=numknight;k++)

        zonghe[i][j]+=dist[k][i][j];

    for(int i=1;i<=R;i++)

        for(int j=1;j<=C;j++)

       {

           lala=zonghe[i][j]+kingdist[i][j];

           if(lala<min1)min1=lala;

           for(int l=1;l<=numknight;l++)

           {

               lala=zonghe[i][j]-dist[l][i][j];

               lala+=dist[l][king[0]][king[1]];

               lala+=disttoking[num][i][j];

               if(lala<min1)min1=lala;

               int bu=0;

               for(int i1=0;i1<8;i1++)

               {

                   int s[2],shu=1;

                   s[0]=king[0]+moveking[i1][0];

                   s[1]=king[1]+moveking[i1][1];

                   while(s[0]>0&&s[0]<=R&&s[1]>0&&s[1]<=C)

                   {

                       lala=disttoking[bu][i][j];

                       lala+=dist[l][s[0]][s[1]];

                       lala+=shu;

                       lala+=(zonghe[i][j]-dist[l][i][j]);

                       shu++;

                       bu++;

                       if(lala<min1)min1=lala;

                       s[0]=s[0]+moveking[i1][0];

                       s[1]=s[1]+moveking[i1][1];

                   }

               }

           }

       }

    cout<<min1<<endl;

 return 0;

}

void bfs(int s[2],int move[8][2],int dist1[27][41])

{

    bool done[27][41];

    queue<aaaa>q;

    while(!q.empty())q.pop();

    for(int i=1;i<=R;i++)for(int j=1;j<=C;j++){done[i][j]=false;dist1[i][j]=99999999;}

    dist1[s[0]][s[1]]=0;

    q.push((aaaa){s[0],s[1],0});

    done[s[0]][s[1]]=true;

    while(!q.empty()){

        aaaa key=q.front();

        q.pop();

        for(int i=0;i<8;i++)

        {

            aaaa kk;

            kk.x=key.x+move[i][0];

            kk.y=key.y+move[i][1];

            if(kk.x>0&&kk.x<=R&&kk.y>0&&kk.y<=C&&!done[kk.x][kk.y]){

                done[kk.x][kk.y]=true;

                dist1[kk.x][kk.y]=key.d+1;

                kk.d=key.d+1;

                q.push(kk);

            }

        }

}

}

可能这个更清楚:

#include<stdio.h>
#include<stdlib.h>
 
#define LENQUE 781
#define INFI 500
FILE *fin,*fout;
int R,C;
int dist[781][31][27];
int total[31][27];
int distking[31][27];
int distride[120][31][27];
int numride;
int king[2];
int numknight;
int knight[781][2];
int moveknight[8][2]={
{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1}
};
int moveking[8][2]={
{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}
};
int queue[LENQUE][3];
bool done[31][27];
 
void bfs(int s[2],int move[8][2],int distmemo[31][27]){
int i,j;
for(i=0;i<R;i++)for(j=0;j<C;j++)done[i][j]=false;
for(i=0;i<R;i++)for(j=0;j<C;j++)distmemo[i][j]=INFI;
distmemo[s[0]][s[1]]=0;
done[s[0]][s[1]]=true;
int head=0,tail=1;
queue[0][0]=s[0];
queue[0][1]=s[1];
queue[0][2]=0;
while(head!=tail){
for(i=0;i<8;i++){
int temp[2];
temp[0]=queue[head][0]+move[i][0];
temp[1]=queue[head][1]+move[i][1];
if(temp[0]>=0&&temp[0]<R&&temp[1]>=0&&temp[1]<=C){
if(!done[temp[0]][temp[1]]){
queue[tail][0]=temp[0];
queue[tail][1]=temp[1];
queue[tail][2]=queue[head][2]+1;
done[temp[0]][temp[1]]=true;
distmemo[temp[0]][temp[1]]=queue[tail][2];
tail=(tail+1)%LENQUE;
}
}
}
head=(head+1)%LENQUE;
}
}
 
int main(){
fin=fopen("camelot.in","r");
fout=fopen("camelot.out","w");
fscanf(fin,"%d %d\n",&R,&C);
char col;
int row;
fscanf(fin,"%c %d",&col,&row);
king[0]=row-1;
king[1]=col-'A';
while(fscanf(fin,"%c",&col)!=EOF){
if(col==' '||col=='\n')continue;
fscanf(fin,"%d",&row);
knight[numknight][0]=row-1;
knight[numknight][1]=col-'A';
numknight++;
}
int i;
bfs(king,moveking,distking);
for(i=0;i<8;i++){
int temp[2];
temp[0]=king[0]+moveking[i][0];
temp[1]=king[1]+moveking[i][1];
while(temp[0]>=0&&temp[0]<R&&temp[1]>=0&&temp[1]<C){
bfs(temp,moveknight,distride[numride++]);
temp[0]=temp[0]+moveking[i][0];
temp[1]=temp[1]+moveking[i][1];
}
}
bfs(king,moveknight,distride[numride++]);
for(i=0;i<numknight;i++){
bfs(knight[i],moveknight,dist[i]);
}
int min=0x7fffffff;
int gr,gc,ride,d,move;
for(gr=0;gr<R;gr++)for(gc=0;gc<C;gc++){
for(i=0;i<numknight;i++){
total[gr][gc]+=dist[i][gr][gc];
}
}
for(gr=0;gr<R;gr++)for(gc=0;gc<C;gc++){
d=distking[gr][gc]+total[gr][gc];
if(d<min)min=d;
for(ride=0;ride<numknight;ride++){
d=distride[numride-1][gr][gc];
d+=dist[ride][king[0]][king[1]];
d+=total[gr][gc]-dist[ride][gr][gc];
if(d<min)min=d;
int po=0,countking=0;
for(i=0;i<8;i++){
int temp[2];
temp[0]=king[0]+moveking[i][0];
temp[1]=king[1]+moveking[i][1];
countking=1;
while(temp[0]>=0&&temp[0]<R&&temp[1]>=0&&temp[1]<C){
d=distride[po][gr][gc];
d+=countking;
d+=dist[ride][temp[0]][temp[1]];
d+=total[gr][gc]-dist[ride][gr][gc];
if(d<min)min=d;
po++;
countking++;
temp[0]=temp[0]+moveking[i][0];
temp[1]=temp[1]+moveking[i][1];
}
}
}
}
fprintf(fout,"%d\n",min);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: