题意是,国王和很多骑士在棋盘的不同位置,国王要和骑士在一点聚集。
若某个骑士和国王相遇之后,骑士和国王共同走一步,只算一步。等于是骑士背上了国王,国王不再走路。
第一遍我的算法用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; }
时间: 2024-10-19 16:02:02