HDU 4311 4312 切比雪夫距离与曼哈顿距离

HDU 4311

题意

二维坐标系上给出n个点,要求在n个点中选定一个点作为中点,使得其它所有点到该点的曼哈顿距离之和最小

曼哈顿距离也叫都市距离,计算公式d = |x1-x2|+|y1-y2|

解决

x轴和y轴独立,分开来做
枚举每一个点当做中点的情况,但是n^2的算法会超时

  1. 按x坐标升序排序
  2. 第一个点扫n-1次求得以第一个点作为中点的x轴距离之和
  3. sumx[i] = sum[i-1]+(2*(i-1)-n)*(node[i].x-node[i-1].x);进行递推
  4. 上面的式子可以这样思考,从i-1到i,前面有i-1个点,需要加上(i-1)(node[i].x-node[i-1].x),后面(包括他自己)有n-(i-1)个点,又要再减去(n-(i-1))(node[i].x-node[i-1].x)
struct Node
{
    ll x,y;
    int id;
    Node(){}
    Node(ll xx,ll yy,int ii){
        x = xx;
        y = yy;
        id = ii;
    }
};
bool cmpx(Node n1 , Node n2) { return n1.x < n2.x; }
bool cmpy(Node n1 , Node n2) { return n1.y < n2.y; }
Node node[maxn];
ll sumx[maxn] , sumy[maxn];
int main()
{
    int T;
    ll x,y;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        rep(i,1,n+1){
            scanf("%lld%lld",&x,&y);
            node[i] = Node(x,y,i);
        }
        sort(node+1,node+1+n,cmpx);
        sumx[node[1].id] = 0;
        rep(i,2,n+1) sumx[node[1].id]+=node[i].x-node[1].x;
        rep(i,2,n+1) sumx[node[i].id] = sumx[node[i-1].id]+(2*(i-1)-n)*(node[i].x-node[i-1].x);
        //rep(i,1,n+1) printf("%3d%c",i,i==n?'\n':' ');
        //rep(i,1,n+1) printf("%3lld%c",sumx[node[i].id],i==n?'\n':' ');
        sort(node+1,node+1+n,cmpy);
        sumy[node[1].id] = 0;
        rep(i,2,n+1) sumy[node[1].id]+=node[i].y-node[1].y;
        rep(i,2,n+1) sumy[node[i].id] = sumy[node[i-1].id]+(2*(i-1)-n)*(node[i].y-node[i-1].y);
        //rep(i,1,n+1) printf("%3lld%c",sumx[node[i].id],i==n?'\n':' ');
        ll ans = INF;
        rep(i,1,n+1) ans = min(ans , sumx[node[i].id]+sumy[node[i].id]);
        cout<<ans<<endl;
    }
}

HDU 4312

题意

一个点可以在1个时间内到达相邻的八连通块,了解一下切比雪夫距离可以知道这个也就是切比雪夫距离
求解切比雪夫距离可以对变换后的坐标求解曼哈顿距离得到

//对于(x,y),将其转换为切比雪夫坐标(x+y,x-y)
//求曼哈顿距离(都市距离)之后除以2就是切比雪夫距离
struct Node
{
    ll x,y;
    int id;
    Node(){}
    Node(ll xx,ll yy,int ii){
        x = xx;
        y = yy;
        id = ii;
    }
};
bool cmpx(Node n1 , Node n2) { return n1.x < n2.x; }
bool cmpy(Node n1 , Node n2) { return n1.y < n2.y; }
Node node[maxn];
ll sumx[maxn] , sumy[maxn];

int main()
{
    int T;
    ll x,y;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        rep(i,1,n+1){
            scanf("%lld%lld",&x,&y);
            node[i] = Node(x+y,x-y,i);
        }
        sort(node+1,node+1+n,cmpx);
        sumx[node[1].id] = 0;
        rep(i,2,n+1) sumx[node[1].id]+=node[i].x-node[1].x;
        rep(i,2,n+1) sumx[node[i].id] = sumx[node[i-1].id]+(2*(i-1)-n)*(node[i].x-node[i-1].x);
        //rep(i,1,n+1) printf("%3d%c",i,i==n?'\n':' ');
        //rep(i,1,n+1) printf("%3lld%c",sumx[node[i].id],i==n?'\n':' ');
        sort(node+1,node+1+n,cmpy);
        sumy[node[1].id] = 0;
        rep(i,2,n+1) sumy[node[1].id]+=node[i].y-node[1].y;
        rep(i,2,n+1) sumy[node[i].id] = sumy[node[i-1].id]+(2*(i-1)-n)*(node[i].y-node[i-1].y);
        //rep(i,1,n+1) printf("%3lld%c",sumx[node[i].id],i==n?'\n':' ');
        ll ans = INF;
        rep(i,1,n+1) ans = min(ans , sumx[node[i].id]+sumy[node[i].id]);
        cout<<ans/2<<endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值