zoukankan      html  css  js  c++  java
  • 【BZOJ】1696: [Usaco2007 Feb]Building A New Barn新牛舍(贪心)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1696

    原题要求min(sum{|x-xi|+|y-yi|}),且一定要看题:“没有两头牛的吃草位置是相邻的”。。。。。。。。。噗,,我就说我怎么能造出反例。。原来我没看题。。

    其实sum和min都可以拆开的T_T,我没意识到啊。。

    求min( sum{|x-xi|} + sum{|y-yi|} )

    我们来考虑,怎么最小化他们。。。

    画条数轴。。。。。。然后。。。找中位数T_T

    我小学森都不如

    。。

    那么思路很清晰了,,,

    对于奇数。只有一个中位数,那么我们找1~n所有x的中位数和y的中位数,,这个就是它的点。。但是要注意,这个点不能和牛重合。如果重合,那么就取牛的上下左右四个点,即“没有两头牛的吃草位置是相邻的”,可以证明这是最优。。

    对于偶数。有2个中位数,,那么我们就要找这两个中位数中所有的可行点。(其实这个范围内所有的点都是可行点,即答案有(xx-x+1)*(yy-y+1)个。。但是注意,这里面不能有牛,所以每找到一个牛,就要减去一个答案。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << #x << " = " << x << endl
    #define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; }
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const int min(const int &a, const int &b) { return a<b?a:b; }
    
    const int N=10005;
    struct dat { int x, y; }a[N];
    bool cmpx(const dat &a, const dat &b) { return a.x<b.x; }
    bool cmpy(const dat &a, const dat &b) { return a.y<b.y; }
    int n, ans1, ans2;
    bool check(int x, int y) {
    	for1(i, 1, n) if(a[i].x==x && a[i].y==y) return 0;
    	return 1;
    }
    int main() {
    	read(n);
    	for1(i, 1, n) read(a[i].x), read(a[i].y);
    	if(n&1) {
    		int x, y;
    		sort(a+1, a+1+n, cmpx); x=a[(n>>1)+1].x;
    		sort(a+1, a+1+n, cmpy); y=a[(n>>1)+1].y;
    		if(check(x, y)) {
    			for1(i, 1, n) ans1+=abs(x-a[i].x)+abs(y-a[i].y);
    			ans2=1;
    		}
    		else {
    			static int tp[4];
    			CC(tp, 0);
    			int fx[]={x+1, x-1, x, x}, fy[]={y, y, y-1, y+1}; ans1=~0u>>1;
    			for1(i, 1, n) rep(j, 4) tp[j]+=abs(fx[j]-a[i].x)+abs(fy[j]-a[i].y);
    			rep(j, 4) if(ans1>tp[j]) ans1=tp[j], ans2=1; else if(ans1==tp[j]) ++ans2;
    		}
    	}
    	else {
    		int x, y, xx, yy;
    		sort(a+1, a+1+n, cmpx); x=a[(n>>1)].x; xx=a[(n>>1)+1].x;
    		sort(a+1, a+1+n, cmpy); y=a[(n>>1)].y; yy=a[(n>>1)+1].y;
    		ans2=(xx-x+1)*(yy-y+1);
    		for1(i, 1, n) {
    			if(a[i].x>=x && a[i].x<=xx && a[i].y>=y && a[i].y<=yy) --ans2;
    			ans1+=abs(x-a[i].x)+abs(y-a[i].y);
    		}
    	}
    	printf("%d %d", ans1, ans2);
    	return 0;
    }
    

    Description

    经 过多年的积蓄,农夫JOHN决定造一个新的牛舍。他知道所有N(2 <= N <= 10,000)头牛的吃草位置,所以他想把牛舍造在最方便的地方。 每一头牛吃草的位置是一个整数点(X_i, Y_i) (-10,000 <= X_i <= 10,000; -10,000 <= Y_i <= 10,000)。 没有两头牛的吃草位置是相邻的。 JOHN决定把牛舍造在一个没有牛吃草的整数点上。如果牛舍在(X, Y),在(X_i, Y_i)的牛到牛舍的距离是|X-X_i|+|Y-Y_i|。 JOHN把牛舍造在哪儿才能使所有牛到牛舍的距离和最低?

    Input

    第1行: 一个数,N。

    第2~N+1行:第i+1行 包含第i头牛的位置(X_i, Y_i)。

    Output

    第1行: 两个数,最小距离和和所有可能达到这个距离和的牛舍位置的数目。

    Sample Input

    4
    1 -3
    0 1
    -2 1
    1 -1

    输入解释:

    一共有4头牛,位置分别为(1, -3), (0, 1), (-2, 1), 和(1, -1).

    Sample Output

    10 4

    输出解释:
    最小距离和是10,可以在牛舍位于 (0, -1), (0, 0), (1, 0), (1, 1)时达到。

    HINT

    Source

  • 相关阅读:
    053-509
    053-298
    053-255
    css实现省略号
    github上写blog
    解决内容被挤压缩小问题
    request.getRequestDispather().forward()与response.sendRedirect()
    资料,来自HTML5前端开发学习⑤群
    checkbox与jq<转>2
    checkbox与jq<转>
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/3969025.html
Copyright © 2011-2022 走看看