zoukankan      html  css  js  c++  java
  • 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 }

     

     

  • 相关阅读:
    PHP 小方法之 算生日
    PHP 小方法之 随机生成几位字符串
    PHP 小方法之 过滤参数
    PHP 小方法之 计算两个时间戳之间相差的日时分秒
    PHP 小方法之 仿百度蜘蛛采集
    PHP 小方法之 显示 今天 昨天 上周 上月 近三月 的时间
    PHP保留两位小数的几种方法
    mysql 常用命令(一)
    PHP数据库页面增删查
    PHP数据库登陆注册简单做法
  • 原文地址:https://www.cnblogs.com/codeyuan/p/4271394.html
Copyright © 2011-2022 走看看