UVa 1511 - Soju

网上有其他的贪心做法 , 我介绍另外一个思路(如yifan 和 purefrog)
抓住题目一个条件 , p1的所有点的x坐标都比p2的小
对于p1的点来说 , 如果有i , j , 且xi>xj , abs(yi-yj)<= xi-xj 那么点j 将是没有意义的 , 想想为什么 ,p2点集的同理可见
[以下是对p1的操作的证明 , p2的同理啦

提示:
s1 s2 为p1点集中的两个点,且满足s1.x>s2.x ;
s3为p2点集中的**任意**一个点

d1 = s3.x-s1.x+abs(s3.y-s1.y);
d2 = s3.x-s2.x+abs(s3.y-s2.y);
d1-d2 = s2.x-s1.x+abs(s3.y-s1.y)-abs(s3.y-s1.y+(s1.y-s2.y))
如果d1-d2恒小于等于0 , 那么s2就是没有意义的
d1-d2<=0 
-> s1.x-s2.x>=abs(s3.y-s1.y)-abs(s3.y-s1.y+(s1.y-s2.y))
>=abs(s3.y-s1.y)-(abs(s3.y-s1.y)+abs(s1.y-s2.y)) 
= abs(s1.y-s2.y)


以上是很严格的推倒 , 但是其实想象一下也就可以了,对于p1的两个点 , 到p2任何一个点的曼哈顿距离取决于x和y , 而无论p2中取哪个点x的差别是一定的 , 如果x坐标相对离得较远的点想在总距离上追赶上x坐标离得近的那个点 , 肯定y要更靠近 , 并且比另一个要靠近的距离要大于两个x坐标的绝对值 , 但是如果两个y的差的绝对值都不及x的差的绝对值的话肯定是不行的;

//
//  main.cpp
//  UVa1511
//
//  Created by Fuxey on 15/8/3.
//  Copyright (c) 2015年 corn.crimsonresearch. All rights reserved.
//

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;
typedef pair<int, int> pii;
pii a[110000] , b[110000] , aa[110000] , bb[110000];

int main(int argc, const char * argv[]) {

    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n , m;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d%d",&a[i].first,&a[i].second);
        scanf("%d",&m);
        for(int i=1;i<=m;i++) scanf("%d%d",&b[i].first,&b[i].second);
        sort(a+1, a+1+n);
        sort(b+1, b+1+m);

        int ca=0 , cb=0;
        for(int i=n;i>=1;i--)
        {
            bool ok=1;
            for(int j=1;j<=ca;j++) 
               if(aa[j].first-a[i].first>= abs(aa[j].second-a[i].second)) { ok=0; break; }
            if(ok) aa[++ca] = a[i];
        }

        for(int i=1;i<=m;i++)
        {
            bool ok=1;
            for(int j=1;j<=cb;j++) if(b[i].first-bb[j].first>= abs(bb[j].second-b[i].second)) { ok=0; break; }
            if(ok) bb[++cb] = b[i];
        }
        int ans = (1<<30);
        for(int i=1;i<=ca;i++) for(int j=1;j<=cb;j++) ans = min(ans , abs(aa[i].first-bb[j].first)+abs(aa[i].second-bb[j].second));
        printf("%d\n",ans);
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值