输入数据:文件camelot.in包括了以字符串表示的棋盘初始状态。该字符串包含了一串最多有64个不同的棋子位置:首先是国王的位置,而随后是武士们的位置。每个位置由一对字母-数字表示:字母表示棋盘水平坐标,而数字表示棋盘垂直坐标。
输入实例:
D4A3A8H1H8
输出数据:
文件camelot.out必须包含单一的一行,以一个正整数表示选手要实现聚会所需最少的移动次数。
输出实例:
10
分析:枚举+floyd
点——方格
边——马步边、王步边
国王与骑士相遇点:携带点
设D[x1,y1,x2,y2]——任意两点之间的最短路(骑)
proc. 求D值
D[]全置∞
D[x1,y1,x1,y1]置0 //同一点最短路为0
d[]两点之间有马步关系 置1
用Floyd 求D[]的值
主:
min=∞;
枚举“聚集点”
Tot=n个骑士到聚集点的总步数
if tot>=min 则 continue;
枚举n个骑士
枚举携带点位置 //注意:这里枚举点都是两重循环。
if tot-带王骑士到聚集点步数+带国王骑士到“携带点”步数+再到聚集点步数+国王到“携带点”步数 输出min; *判断马步关系只需看横坐标绝对值*纵坐标绝对值是否为2 *国王到“携带点”步数=max{横坐标差,纵坐标差} 下面是写得很烂的程序:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
int kgx,kgy,i,j,k,l,n,x,y,tot,min;
int d[10][10][10][10],a[70],b[70];
char s[200];
int max(int a,int b){
return a>b?a:b;
}
void Floyd(){
int i,j,k,l,kx,ky,ix,iy,jx,jy;
memset(d,30000,sizeof(d));
for (i=1;i<=8;i++)
for (j=1;j<=8;j++)
d[i][j][i][j]=0;
for (i=1;i<=8;i++)
for (j=1;j<=8;j++)
for (k=1;k<=8;k++)
for (l=1;l<=8;l++)
if (abs(i-k)*abs(j-l)==2)
d[i][j][k][l]=1;
for (kx=1;kx<=8;kx++)
for (ky=1;ky<=8;ky++)
for (ix=1;ix<=8;ix++)
for (iy=1;iy<=8;iy++)
for (jx=1;jx<=8;jx++)
for (jy=1;jy<=8;jy++){
if (d[ix][iy][jx][jy]>(d[ix][iy][kx][ky]+d[kx][ky][jx][jy]))
d[ix][iy][jx][jy]=d[ix][iy][kx][ky]+d[kx][ky][jx][jy];
}
}
int main(){
freopen("camelot.in","r",stdin);
freopen("camelot.out","w",stdout);
gets(s);
kgx=s[0]-64;
kgy=s[1]-48;
for (i=2;i<strlen(s);i++){
if (i%2==0) a[i/2]=s[i]-'A'+1;
else b[i/2]=s[i]-'0';
}
n=strlen(s)/2-1;
Floyd();
min=32767;
for (i=1;i<=8;i++)
for (j=1;j<=8;j++){
tot=0;
for (k=1;k<=n;k++){
tot+=d[a[k]][b[k]][i][j];
if (tot>=min) continue;
}
for (k=1;k<=n;k++)
for (x=1;x<=8;x++)
for (y=1;y<=8;y++)
if (tot-d[a[k]][b[k]][i][j]+d[a[k]][b[k]][x][y]+d[x][y][i][j]+max(abs(kgx-x),abs(kgy-y))<min){
min=tot-d[a[k]][b[k]][i][j]+d[a[k]][b[k]][x][y]+d[x][y][i][j]+max(abs(kgx-x),abs(kgy-y));
}
}
printf("%d",min);
return 0;
}