USACO Training3.3亚瑟王的宫殿【搜索】By cellur925
因为太蒟了,所以参考了dalao@zbtrs == 对此表示感谢并侵删。
看起来我们就知道这是搜索题。
最后的情况分两种:有骑士背国王/国王自食其力走到集合点。
首先,我们不知道大家最后集合在哪里,所以可以枚举一下这个点。
其次,我们不知道是哪个骑士背,所以再枚举一下。
再次,我们不知道在哪里接国王,所以再枚举一下这个点。
这是思路的大体框架。然后在更新答案时,我们需要求出在棋盘上一个点到另一点的最短距离。然后因为我们可以等效的认为这是一个无向无环图,所以直接用bfs顺便跑出最短距离就行了==。
细节:赋初值。dis数组和ans都要赋成正无穷。因为我们在寻求一个最小值。
优化:最优性剪枝(代码中)
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 ID:cellur_2 3 TASK:camelot 4 LANG:C++ 5 */ 6 #include<cstdio> 7 #include<algorithm> 8 #include<queue> 9 #include<cstring> 10 11 using namespace std; 12 const int inf=0x3f3f3f; 13 14 int n,m,cnt,ans=inf; 15 char ch[5]; 16 bool vis[41][27]; 17 int dx[10]={0,-2,-1,1,2,2,1,-1,-2}; 18 int dy[10]={0,1,2,2,1,-1,-2,-2,-1}; 19 int dis[41][27][41][27]; 20 int kingx,kingy; 21 struct point{ 22 int x,y; 23 }knight[2000]; 24 25 bool valid(int x,int y) 26 { 27 if(x>=1&&x<=n&&y>=1&y<=m) return 1; 28 return 0; 29 } 30 31 void bfs(int x,int y) 32 { 33 queue<pair<int,int> >q; 34 q.push(make_pair(x,y)); 35 memset(vis,0,sizeof(vis)); 36 vis[x][y]=1; 37 dis[x][y][x][y]=0; 38 while(!q.empty()) 39 { 40 int xx=q.front().first; 41 int yy=q.front().second; 42 q.pop(); 43 int step=dis[x][y][xx][yy]; 44 for(int i=1;i<=8;i++) 45 { 46 int rx=xx+dx[i]; 47 int ry=yy+dy[i]; 48 if(valid(rx,ry)&&!vis[rx][ry]) 49 { 50 dis[x][y][rx][ry]=step+1; 51 q.push(make_pair(rx,ry)); 52 vis[rx][ry]=1; 53 } 54 } 55 } 56 } 57 58 int main() 59 { 60 freopen("camelot.in","r",stdin); 61 freopen("camelot.out","w",stdout); 62 scanf("%d%d",&n,&m); 63 scanf("%s",ch+1);kingy=(int)ch[1]-'A'+1; 64 scanf("%d",&kingx);kingx=n-kingx+1; 65 while(scanf("%s",ch+1)!=EOF) 66 { 67 knight[++cnt].y=(int)ch[1]-'A'+1; 68 scanf("%d",&knight[cnt].x); 69 knight[cnt].x=n-knight[cnt].x+1; 70 } 71 for(int i=1;i<=n;i++) 72 for(int j=1;j<=m;j++) 73 for(int a=1;a<=n;a++) 74 for(int b=1;b<=m;b++) 75 dis[i][j][a][b]=inf; 76 for(int i=1;i<=n;i++) 77 for(int j=1;j<=m;j++) 78 bfs(i,j); 79 for(int i=1;i<=n;i++) 80 for(int j=1;j<=m;j++) 81 { 82 int tmp=0; 83 for(int k=1;k<=cnt;k++) 84 tmp+=dis[knight[k].x][knight[k].y][i][j]; 85 ans=min(ans,tmp+max(abs(kingx-i),abs(kingy-j))); 86 //先考虑国王不被帮助运送的情况 87 for(int k=1;k<=cnt;k++) 88 {//需要重开变量,不能偷懒用tmp直接减,否则会一直减 89 int tmpp=tmp-dis[knight[k].x][knight[k].y][i][j]; 90 if(tmp>=ans) continue;//最优性剪枝 91 for(int l=1;l<=n;l++) 92 for(int r=1;r<=m;r++) 93 ans=min(ans,tmpp+dis[knight[k].x][knight[k].y][l][r]+dis[l][r][i][j]+max(abs(kingx-l),abs(kingy-r))); 94 } 95 } 96 printf("%d\n",ans); 97 return 0; 98 }
独立意志与自由思想是必须争的,且须以生死力争。