【JZOJ4622】亚瑟王之宫

Description

这里写图片描述

Solution

这题时限开的挺大的。。。

由于时限较大,我们可以预处理出每个坐标走日字步到另一坐标的最短距离, O(r3c3) 的Floyd可以解决(可以考虑用spfa,但这里的点入队时间较长)。

然后我们枚举两个汇合点,我们贪心的想,一个骑士走到第一个坐标距离如果比走到第二个的小的多,那么我们肯定不走到第二个坐标,反之就不走到第一个坐标。

于是,设第 i 个骑士到坐标A的距离为ai,到B的距离为 bi ,那么把所有骑士按照 aibi 排个序,取前 N2 个走到A,剩下的走到B,对答案取 min 即可。

Code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 21
#define ll long long
using namespace std;
int f[N][N][N][N];
struct node{
    int x,y,z;
}a[N*N];
bool cmp(node x,node y)
{
    return x.z<y.z;
}
int fx[8][2]={{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}};
int main()
{
    freopen("4622.in","r",stdin);
    freopen("4622.out","w",stdout);
    int n,r,c;
    cin>>n>>r>>c;
    fo(i,1,n)
    scanf("%d %d",&a[i].x,&a[i].y);
    memset(f,60,sizeof(f));
    fo(i,1,r)
    fo(j,1,c)
    fo(k,0,7)
    f[i][j][i+fx[k][0]][j+fx[k][1]]=1;
    fo(i,1,r)
    fo(j,1,c)
    f[i][j][i][j]=0;
    fo(kx,1,r)
    fo(ky,1,c)
    fo(ix,1,r)
    fo(iy,1,c)
    fo(jx,1,r)
    fo(jy,1,c)
    if(f[ix][iy][jx][jy]>f[ix][iy][kx][ky]+f[kx][ky][jx][jy])
    f[ix][iy][jx][jy]=f[ix][iy][kx][ky]+f[kx][ky][jx][jy];
    int ans=2147483647;
    fo(i1,1,r)
    fo(j1,1,c)
    fo(i2,1,r)
    fo(j2,1,c)
    {
        if(i1==i2 && j1==j2) continue;
        int tmp=0;
        fo(k,1,n)
        a[k].z=f[a[k].x][a[k].y][i1][j1]-f[a[k].x][a[k].y][i2][j2];
        sort(a+1,a+n+1,cmp);
        fo(k,1,n/2) tmp+=f[a[k].x][a[k].y][i1][j1];
        fo(k,n/2+1,n) tmp+=f[a[k].x][a[k].y][i2][j2];
        if(tmp<ans) ans=tmp;
    }
    cout<<ans;
}
posted @ 2016-07-14 08:19  sadstone  阅读(59)  评论(0编辑  收藏  举报