【NOIP2016A组模拟7.13】亚瑟王之宫 题解+代码

37 篇文章 0 订阅
17 篇文章 0 订阅

Description

这里写图片描述

Input

这里写图片描述

output

答案

Sample Input

4 4 4
1 1
4 1
1 4
4 4

Sample Output

4

Data Constraint

R,C<=20,N<=200

Solution

乍一看感觉挺难,结果发现R,C只有20,乘起来也就400, O(n3) 都不会爆。
于是可以预处理出两个点之间的最短距离(这里的最短距离都是指日字跳的)Floyd搞定。
然后枚举出两个会合点,对于每个点,按照它与两个点的距离差排序。前n/2个会合到第一个点,后n/2个会合到第二个点。
注意Floyd不要打错。

Code

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 300
#define h(i,j) ((i-1)*c+j)
using namespace std;
int n,r,c,map[410][410];
struct note{
    int x,y;
};
note a[N],b[N];
bool cnt(note x,note y){return x.x<y.x;}
int main()
{
    scanf("%d%d%d",&n,&r,&c);
    fo(i,1,n) scanf("%d%d",&a[i].x,&a[i].y);
    fo(i,1,400) fo(j,1,400) map[i][j]=100000000;
    fo(i,1,r)
    {
        fo(j,1,c)
        {
            if(i+1<=r&&j+2<=c)map[h(i,j)][h(i+1,j+2)]=1;
            if(j-2>0&&i+1<=r)map[h(i,j)][h(i+1,j-2)]=1;
            if(i-1>0&&j+2<=c)map[h(i,j)][h(i-1,j+2)]=1;
            if(i-1>0&&j-2>0)map[h(i,j)][h(i-1,j-2)]=1;
            if(i+2<=r&&j+1<=c)map[h(i,j)][h(i+2,j+1)]=1;
            if(j-1>0&&i+2<=r)map[h(i,j)][h(i+2,j-1)]=1;
            if(i-2>0&&j+1<=c)map[h(i,j)][h(i-2,j+1)]=1;
            if(j-1>0&&i-2>0)map[h(i,j)][h(i-2,j-1)]=1;
        }
    }
    fo(k,1,r*c)
        fo(i,1,r*c)
        {
            map[i][i]=0;
            fo(j,1,r*c)
            map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
        }
    int ans=2147483647;
    fo(i,1,r*c)
    {
        fo(j,1,r*c)
        if(i!=j)
        {
            int jy=0;
            fo(k,1,n)
            {
                b[k].x=(map[h(a[k].x,a[k].y)][i]-map[h(a[k].x,a[k].y)][j]);
                b[k].y=k;
            }
            sort(b+1,b+1+n,cnt);
            fo(k,1,n)
            {
                int l=b[k].y;
                if (k<=n/2) jy=jy+map[h(a[l].x,a[l].y)][i];
                else jy=jy+map[h(a[l].x,a[l].y)][j];
            }
            ans=min(ans,jy);
        }
    }
    printf("%d",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值