POJ 1178 预处理+枚举+floyd

Camelot
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 2839   Accepted: 1334

Description

Centuries ago, King Arthur and the Knights of the Round Table used to meet every year on New Year's Day to celebrate their fellowship. In remembrance of these events, we consider a board game for one player, on which one king and several knight pieces are placed at random on distinct squares.
The Board is an 8x8 array of squares. The King can move to any adjacent square, as shown in Figure 2, as long as it does not fall off the board. A Knight can jump as shown in Figure 3, as long as it does not fall off the board.

During the play, the player can place more than one piece in the same square. The board squares are assumed big enough so that a piece is never an obstacle for other piece to move freely.
The player's goal is to move the pieces so as to gather them all in the same square, in the smallest possible number of moves. To achieve this, he must move the pieces as prescribed above. Additionally, whenever the king and one or more knights are placed in the same square, the player may choose to move the king and one of the knights together henceforth, as a single knight, up to the final gathering point. Moving the knight together with the king counts as a single move.

Write a program to compute the minimum number of moves the player must perform to produce the gathering.

Input

Your program is to read from standard input. The input contains the initial board configuration, encoded as a character string. The string contains a sequence of up to 64 distinct board positions, being the first one the position of the king and the remaining ones those of the knights. Each position is a letter-digit pair. The letter indicates the horizontal board coordinate, the digit indicates the vertical board coordinate.

0 <= number of knights <= 63

Output

Your program is to write to standard output. The output must contain a single line with an integer indicating the minimum number of moves the player must perform to produce the gathering.

Sample Input

D4A3A8H1H8

Sample Output

10

Source

 

POJ 1178解题思路:

1.枚举最后的相遇点、与国王相遇的骑士以及国王与骑士的相遇点,复杂度O(64*n*64);

2.首先预处理一下,把骑士走时任意两点间的最短路,国王走时任意两点间的最短路都算出来;

3.首先枚举一个目的地,计算出所有的骑士到目的地的距离sum,然后再枚举一个骑士为携带国王的骑士,最后枚举骑士与国王的相遇点。每一次枚举的答案为:

ans[i]=sum+相应骑士从初始点到相遇点的距离+骑士从相遇点到终点的距离+国王从初始点到相遇点的距离-相应骑士从初始点到终点的距离;

ans=min(ans[i]);

 

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cstdlib>
  6 using namespace std;
  7 const int inf=0x3fffffff;
  8 int next_king[8][2]={{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
  9 int next_knight[8][2]={{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}};
 10 int minpath_king[64][64],minpath_knight[64][64];
 11 int top;
 12 char str[300];
 13 struct point
 14 {
 15     int x,y,pp;
 16 };
 17 point p[100];
 18 bool judge(int xx,int yy)
 19 {
 20     if(xx>=0&&xx<8&&yy>=0&&yy<8) return 1;
 21     return 0;
 22 }
 23 void init()
 24 {
 25     for(int i=0;i<64;i++)
 26     {
 27         for(int j=0;j<64;j++)
 28         {
 29             minpath_king[i][j]=inf;
 30             minpath_knight[i][j]=inf;
 31         }
 32         minpath_king[i][i]=0;
 33         minpath_knight[i][i]=0;
 34         int gx=i/8,gy=i%8;
 35         int tx,ty;
 36         for(int j=0;j<8;j++)
 37         {
 38             tx=gx+next_king[j][0];
 39             ty=gy+next_king[j][1];
 40             if(judge(tx,ty)){
 41                 minpath_king[i][tx*8+ty]=1;
 42             }
 43             tx=gx+next_knight[j][0];
 44             ty=gy+next_knight[j][1];
 45             if(judge(tx,ty)){
 46                 minpath_knight[i][tx*8+ty]=1;
 47             }
 48         }
 49     }
 50 }
 51 void floyd()
 52 {
 53     for(int k=0;k<64;k++)
 54         for(int i=0;i<64;i++)
 55           for(int  j=0;j<64;j++)
 56     {
 57         minpath_king[i][j]=min(minpath_king[i][j],minpath_king[i][k]+minpath_king[k][j]);
 58         minpath_knight[i][j]=min(minpath_knight[i][j],minpath_knight[i][k]+minpath_knight[k][j]);
 59     }
 60 }
 61 int slove()
 62 {
 63     int gx,gy,gp;
 64     int ans=inf,sum=0;
 65     for(int i=0;i<64;i++)//枚举最后的点
 66     {
 67         sum=0;
 68       for(int j=1;j<top;j++)
 69       {
 70           sum+=minpath_knight[i][p[j].pp];
 71       }
 72       for(int j=1;j<top;j++)//枚举携带了国王的骑士
 73         for(int k=0;k<64;k++)//枚举骑士与国王的相遇点
 74         {
 75             sum+=minpath_knight[p[j].pp][k]+minpath_knight[k][i]+minpath_king[p[0].pp][k];
 76             sum-=minpath_knight[i][p[j].pp];
 77             if(sum<ans) ans=sum;
 78             sum-=minpath_knight[p[j].pp][k]+minpath_knight[k][i]+minpath_king[p[0].pp][k];
 79             sum+=minpath_knight[i][p[j].pp];
 80         }
 81     }
 82     return ans;
 83 }
 84 int main()
 85 {
 86    // freopen("in.txt","r",stdin);
 87     scanf("%s",str);char s1,s2;
 88     int l=strlen(str);top=0;
 89     for(int i=0;i<l;i+=2)
 90     {
 91         s1=str[i];s2=str[i+1];
 92         p[top].x=s1-'A';
 93         p[top].y=s2-'1';
 94         p[top].pp=p[top].x*8+p[top].y;
 95         top++;
 96     }
 97     init();floyd();
 98     int ans=slove();
 99     printf("%d
",ans);
100     return 0;
101 }

 

 

原文地址:https://www.cnblogs.com/codeyuan/p/4271394.html