pku1178: Camelot

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[n]=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*/

posted on 2012-07-25 22:07  acmer-jun  阅读(178)  评论(0编辑  收藏  举报

导航