您的位置:首页 > 其它

pku1178: Camelot

2012-07-25 22:07 267 查看
pku1178: http://poj.org/problem?id=1178
题意:给出一行字符串,每对字母+数字表示棋盘上的一点,如A表示横坐标为1,B表示横坐标为2等,第一对表示王,只可上下左右移动,后面每一对表示一个马,走法跟象棋一样(没有算马脚),若马与王到了同一个格子,马可以带着王走,求总的最少需要多少步可使所有马和王汇集到一个格子里
解法:floyd+3个枚举:先用floyd算出马在每个点到其他点的最小步数,再3层枚举:第一层枚举所有成员聚集点,第二层枚举马接王的点,第三层枚举求出马接王再到达聚集点中需要步数最小的马
code:


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
const int inf=1<<29;
int horse[100][100],xh[100],yh[100];
int dx[]={-2,-2,-1,-1,2,2,1,1};
int dy[]={-1,1,-2,2,-1,1,-2,2};
char s[300];
int main()
{
int ans,kx,ky;
while(scanf("%s",&s)!=EOF)
{
ky=s[0]-'A';kx=s[1]-'1';   //王的坐标
int n=0;
for(int i=2;i<strlen(s);i=i+2)  //马的坐标
{
yh
=s[i]-'A';
xh[n++]=s[i+1]-'1';
}
for(int i=0;i<64;i++)   //初始化马从各点到其他点的步数
for(int j=0;j<64;j++)
{
if(i==j)
horse[i][j]=0;
else
horse[i][j]=inf;
}
for(int i=0;i<8;i++)       //可一步到达的先赋值,horse[i][j]表示从i到j的步数
{
for(int j=0;j<8;j++)
{
for(int k=0;k<8;k++)
{
int xx=i+dx[k];
int yy=j+dy[k];
if(xx>=0&&xx<8&&yy>=0&&yy<8)
{
horse[i*8+j][xx*8+yy]=1;
horse[xx*8+yy][i*8+j]=1;
}
}
}
}
for(int k=0;k<64;k++)          //floyd
{
for(int i=0;i<64;i++)
{
for(int j=0;j<64;j++)
{
if(horse[i][j]>horse[i][k]+horse[k][j])
horse[i][j]=horse[i][k]+horse[k][j];
}
}
}
int ans=inf;
for(int i=0;i<64;i++)         //枚举最终汇集点
{
for(int j=0;j<64;j++)        //枚举马开始带王走(马与王到达同一个点)的汇合点
{
int sum=abs(j/8-kx)+abs(j%8-ky); //sum为总步数,先加上王自己走到汇合点的步数
int min=inf;
for(int k=0;k<n;k++)
{
sum=sum+horse[xh[k]*8+yh[k]][i];        //sum加上所有马到达汇集点的步数
if(horse[xh[k]*8+yh[k]][j]+horse[j][i]-horse[xh[k]*8+yh[k]][i]<min)
min=horse[xh[k]*8+yh[k]][j]+horse[j][i]-horse[xh[k]*8+yh[k]][i];  //选择与王汇合后再到聚集点的马中步数最少的,注意需要减去重复计算的                                                                                     马直接到达聚集点,也就是把原来直接到达聚集点的路线改为先接王再到达聚集点
}
sum=sum+min;
if(sum<ans)
ans=sum;
}
}
printf("%d\n",ans);
}
}
/*input:
D4A3A8H1H8
output:
10*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: