USACO 3.3.3 camelot

本来这是个简单题,但是两年前第一次做的时候发现它真的太经典了!

 

【camelot】

/*
ID: wangqia6
TASK: camelot
LANG: C++
*/

#include <fstream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;

const long INF = 0x01010100;
const long NMAX = 30;
const long CMAX = 900;
const long KMAX = 8;
const long WMAX = 16;
const long dx[KMAX] = {1,2,-1,-2,-2,1,2,-1};
const long dy[KMAX] = {2,1,-2,-1,1,-2,-1,2};
const long cx[KMAX] = {1,-1,1,-1,0,0,1,-1};
const long cy[KMAX] = {1,-1,-1,1,1,-1,0,0};
const long ex[WMAX] = {2,-2,2,-2,0,0,2,-2,2,2,1,-1,-2,-2,1,-1};
const long ey[WMAX] = {2,-2,-2,2,2,-2,0,0,1,-1,2,2,1,-1,-2,-2};
const long A = long('A') - 1;

struct posi
{
       long x,y;       
};

ifstream fin ("camelot.in");
ofstream fout ("camelot.out");
long n,m,knight_sum = 0,pick_sum = 0,pick_two_sum = 0,
     dist[NMAX][NMAX][NMAX][NMAX],dist_sum,ans = INF;
bool vis[NMAX][NMAX];
posi meet,king,knight[CMAX],pick[KMAX],pick_two[WMAX];
queue<long> quex,quey;

void initdata()
{
     char ch;
     long t;
     
     fin >> n >> m;
     fin >> ch >> king.y;
     king.x = long(ch) - A;
     while (fin >> ch >> t)
     {
           knight[knight_sum].x = long(ch) - A;
           knight[knight_sum].y = t;
           knight_sum++;            
     }
     
     return;     
}

bool check(long a,long b)
{
     if (a < 1) 
        return false;
     if (b < 1)
        return false;
     if (a > m)
        return false;
     if (b > n)
        return false;
     return true;     
}

void get_dist(long sx, long sy)
{
     long tx,ty,i,px,py,dd;
     
     memset(vis,0,sizeof(vis)); 
     vis[sx][sy] = true;
     dist[sx][sy][sx][sy] = 0;
     
     quex.push(sx);
     quey.push(sy);
     while (! quex.empty())
     {
           tx = quex.front();
           ty = quey.front();
           dd = dist[sx][sy][tx][ty];
           
           for (i = 0; i < KMAX; i++)
           {
               px = tx + dx[i];
               py = ty + dy[i];
               if (check(px,py) && (! vis[px][py]))
               {
                  vis[px][py] = true;
                  dist[sx][sy][px][py] = dd + 1;  
                  quex.push(px);
                  quey.push(py);              
               }    
           }
           
           quex.pop();
           quey.pop();
     }
     
     return;     
}

void calc_dist()
{
     long i,j;
     
     memset(dist,0x0f,sizeof(dist));
     for (i = 1; i <= m; i++)
         for (j = 1; j <= n; j++)
             get_dist(i,j);
     
     return;     
}

long king_dist(long i,long j)
{
     return max(abs(king.x - i),abs(king.y - j));     
}

void solve()
{
     long i,j,new_dist;
     
     for (i = 0; i < KMAX; i++)
         if (check(king.x + cx[i],king.y + cy[i]))
         {
            pick[pick_sum].x = king.x + cx[i];
            pick[pick_sum].y = king.y + cy[i];
            pick_sum++;
         }
         
     for (i = 0; i < WMAX; i++)
         if (check(king.x + ex[i],king.y + ey[i]))
         {
            pick_two[pick_two_sum].x = king.x + ex[i];
            pick_two[pick_two_sum].y = king.y + ey[i];
            pick_two_sum++;
         }
     
     for (meet.x = 1; meet.x <= m; meet.x++)
         for (meet.y = 1; meet.y <= n; meet.y++)
         {
             dist_sum = 0;
             for (i = 0; i < knight_sum; i++)
             {
                 dist_sum += dist[meet.x][meet.y][knight[i].x][knight[i].y];
                 if (dist_sum > ans)
                    break;                 
             }

             if (dist_sum > ans)
                continue;   
                
             if (dist_sum + king_dist(meet.x,meet.y) < ans)
                ans = dist_sum + king_dist(meet.x,meet.y);
             
             for (j = 0; j < knight_sum; j++)
             {
                 new_dist = dist_sum - dist[knight[j].x][knight[j].y][meet.x][meet.y] +
                            dist[knight[j].x][knight[j].y][king.x][king.y] +
                            dist[king.x][king.y][meet.x][meet.y];
                 if (new_dist < ans)
                    ans = new_dist;    
             }
                
             for (i = 0; i < pick_sum; i++)
                 for (j = 0; j < knight_sum; j++)
                 {
                     new_dist = dist_sum - dist[knight[j].x][knight[j].y][meet.x][meet.y] +  
                                dist[knight[j].x][knight[j].y][pick[i].x][pick[i].y] + 
                                1 + dist[pick[i].x][pick[i].y][meet.x][meet.y];
                     if (new_dist < ans)
                        ans = new_dist;    
                 }
                 
                 
             for (i = 0; i < pick_two_sum; i++)
                 for (j = 0; j < knight_sum; j++)
                 {
                     new_dist = dist_sum - dist[knight[j].x][knight[j].y][meet.x][meet.y] +  
                                dist[knight[j].x][knight[j].y][pick_two[i].x][pick_two[i].y] + 
                                2 + dist[pick_two[i].x][pick_two[i].y][meet.x][meet.y];
                     if (new_dist < ans)
                        ans = new_dist;    
                 }
         }     
}

void outitdata()
{
     fout << ans << endl;
     fin.close();
     fout.close();     
}

int main()
{
    initdata();
    calc_dist();
    solve();
    outitdata();
    return 0;    
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值