标签:
BFS.先算出棋盘上每个点到各个点knight需要的步数;然后枚举所有点,其中再枚举king是自己到的还是knight带它去的(假如是knight带它的,枚举king周围的2格(网上都这么说,似乎是个结论?还是usaco数据太弱了?不过看跑出来的时间,全部枚举或许也可以))。一开始觉得挺麻烦的,不过只要思路清晰写起来应该也没多大问题。大概就是这样了.
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<queue> #include<cmath> #define rep(i,l,r) for(int i=l;i<=r;i++) #define dow(i,l,r) for(int i=l;i>=r;i--) #define clr(x,c) memset(x,c,sizeof x) using namespace std; const int inf=0x3f3f3f3f,maxr=30+5,maxc=26+5; const int dir[8][2]={{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1}}; int d[maxr][maxc][maxr][maxc]; int r,c,num=0; struct coor { int x,y; }; queue<coor> q; coor king,knight[maxr*maxc]; void init() { cin>>r>>c; char p; int t; cin>>p>>t; king={t,p-‘A‘+1}; while(cin>>p>>t) knight[++num]={t,p-‘A‘+1}; clr(d,inf); rep(i,1,r) rep(j,1,c) { d[i][j][i][j]=0; q.push((coor){i,j}); while(!q.empty()) { coor e=q.front(); q.pop(); rep(k,0,7) { int x=e.x+dir[k][0]; int y=e.y+dir[k][1]; if(x<=0 || x>r || y<=0 || y>c) continue; if(d[i][j][x][y]==inf) { d[i][j][x][y]=d[i][j][e.x][e.y]+1; q.push((coor){x,y}); } } } } } int s() { int ans=inf; int i=5,j=2; rep(i,1,r) rep(j,1,c) { int w=0,t=inf; rep(k,1,num) { coor e=knight[k]; w+=d[i][j][e.x][e.y]; } rep(a,max(king.x-2,1),min(king.x+2,r)) rep(b,max(king.y-2,1),min(king.y+2,c)) rep(k,1,num) { coor e=knight[k]; int x=abs(king.x-a); int y=abs(king.y-b); t=min(t,d[i][j][a][b]+d[a][b][e.x][e.y]+x+y-min(x,y)-d[i][j][e.x][e.y]); } int x=abs(king.x-i); int y=abs(king.y-j); int h=min(x+y-min(x,y),t)+w; ans= h>=0 && h<ans ? h:ans; } return ans; } int main() { freopen("camelot.in","r",stdin); freopen("camelot.out","w",stdout); init(); cout<<s()<<endl; fclose(stdin); fclose(stdout); return 0; }
标签:
原文地址:http://www.cnblogs.com/JSZX11556/p/4293332.html