【u250】manhattan

Time Limit: 1 second
Memory Limit: 64 MB

【问题描述】

混乱的城市已经变得无法控制。大楼随处乱造,城市的布局也是一片混乱。市长决定要结束这种局面,兵器并且想建造一个漂亮的、有组织的城市。
通过一些研究,他找到了使这个成为现实的理想的方法。受到纽约曼哈顿的启发,他希望所有的房子都造在矩形的格子里,用南北向的林荫道和东西向的街道隔开。这些林荫道和街道都有相同的间距。
在现在这种状况,房子已经规划在矩形格子里面了。事实上,每幢房子都恰好完全覆盖住一个矩形格子。但是,所有的楼房随
机地散落在城市里,不毁坏房屋来造路是不可能的。为了使得更多的市民开心,市长想要毁坏尽量少的房子。给你当前的房屋建造
状况,最小破坏量是多少呢?
这里写图片描述
上图说明了这个问题。阴影方块是原先的楼房。如果道路间距为3,上面的粗线条就是规划的道路,被经过的那个楼房就要被拆除了。图对应样例

【输入格式】

输入文件的第一行为两个整数D和N,用一个空格隔开,分别代表道路间距、城市中的楼房数,1 <= D <= 1000, 1 <= N <= 100000。 以下N行,每行两个整数x和y,用一个空格隔开,代表房屋的位置。-109 <= x,y <= 109。

【输出格式】

输出文件只有一行一个整数,代表最少需要毁坏的房屋数。

【数据规模】

Sample Input1

3 10
1 0
2 0
3 0
4 0
1 2
0 3
1 5
3 5
4 2
-2 2

Sample Output1

1

【题目链接】:http://noi.qz5z.com/viewtask.asp?ID=u250

【题解】

这里写图片描述
可以看到我们只要在0..d-1(两个坐标轴都是)的范围内枚举道路放在哪里,其他地方的道路位置就确定了;
则我们把其他位置的房子,全部都放在0..d-1,0..d-1这个坐标范围里面就好了->用取余来替代这个移动的过程;
我们对输入的坐标直接取余->移动到那个最小的矩形区域里面;
然后heng[x]++,heng[y]++,x和y都对d取余过;
然后要记录g[x][y]++;(防止重复计数);
因为如果最后我们在枚举道路在这个最小矩形区域内的坐标(x,y)时(即划一条横线和一条竖线经过x,y,这两条道路由这个点确定出来了,其他的道路也就确定出来了,因为距离一样),但是可能g[x][y]不为0,也就是说那些从其他地方移动过来的点里面有存在于横道路和竖道路的交界处的房子,我们直接加上heng[x]+heng[y]的时候会把那些交界处的房子多算一次;则需要再减掉g[x][y];

【完整代码】

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <set>
#include <map>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <string>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

void rel(LL &r)
{
    r = 0;
    char t = getchar();
    while (!isdigit(t) && t!='-') t = getchar();
    LL sign = 1;
    if (t == '-')sign = -1;
    while (!isdigit(t)) t = getchar();
    while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
    r = r*sign;
}

void rei(int &r)
{
    r = 0;
    char t = getchar();
    while (!isdigit(t)&&t!='-') t = getchar();
    int sign = 1;
    if (t == '-')sign = -1;
    while (!isdigit(t)) t = getchar();
    while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
    r = r*sign;
}

const int MAXN = 1e3+10;
const int dx[5] = {0,1,-1,0,0};
const int dy[5] = {0,0,0,-1,1};
const double pi = acos(-1.0);

int d,n,heng[MAXN],zong[MAXN],g[MAXN][MAXN];

int main()
{
    //freopen("F:\rush.txt","r",stdin);
    rei(d);rei(n);
    rep1(i,1,n)
    {
        int x,y;
        rei(x);rei(y);
        x%=d,y%=d;
        if (x<0) x+=d;
        if (y<0) y+=d;
        heng[x]++,zong[y]++;
        g[x][y]++;
    }
    int ans = 1e5+10;
    rep1(i,0,d-1)
        rep1(j,0,d-1)
            ans = min(ans,heng[i]+zong[j]-g[i][j]);
    cout << ans << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/AWCXV/p/7626926.html