标签:
题意是,国王和很多骑士在棋盘的不同位置,国王要和骑士在一点聚集。
若某个骑士和国王相遇之后,骑士和国王共同走一步,只算一步。等于是骑士背上了国王,国王不再走路。
第一遍我的算法用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;
}
标签:
原文地址:http://www.cnblogs.com/modengdubai/p/4833444.html