Coconuts HDU - 5925 (bfs + 离散化)

Coconuts HDU - 5925 (bfs + 离散化)

题目链接:https://cn.vjudge.net/contest/221692#problem/D
题目大意:就是有r*c的方阵 上面都是白的 其中有n个黑色的点 ,问你黑色的点把白色的点分成了几个部分,每个部分的点有多少。
input:
2

3 3
2
1 2
2 1

3 3
1
2 2
output:
Case #1:
2
1 6
Case #2:
1
8
题目分析:正常的思路就是搜索,但是图太大 0 < R,C≤ 1e9, 会超时, 可是黑色的点少啊,才200,所以突破点应该就在这里。
最终想出用离散化的方法解决这个问题,;
图很大的时候每个点之间的距离很大,只要把这一部分离散化就好了,离散化后 图最坏也只是400*400,这样的话搜索就不会超时了。
然而这个题补了这么久就是卡在离散化这里了。不会二维的离散化…

#include <bits/stdc++.h>
using namespace std;

const int maxn = 3000;
typedef long long ll;

int x[maxn], y[maxn], cntx, cnty, tx[maxn], ty[maxn];
ll p[maxn][maxn];
vector<int> data1, data2;
vector<ll> ans;
bool vis[maxn][maxn];
int dict[4][2] = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};

bool judge(int x, int y) {
   return x >= 1 && x < cntx && y >= 1 && y < cnty && !vis[x][y];
}

ll bfs(int x, int y) {
    queue<pair<int, int> > q;
    ll num = 0;
    vis[x][y] = true;
    q.push(make_pair(x, y));

    while(!q.empty()) {
        int X = q.front().first;
        int Y = q.front().second;
        q.pop();
        num += p[X][Y];

       for(int i = 0; i < 4; i++) {
        int tx = X + dict[i][0];
        int ty = Y + dict[i][1];
        if(judge(tx, ty)) {
            vis[tx][ty] = true;
            q.push(make_pair(tx, ty));
        }
      }
    }
    return num;
}

int main()
{
    int t, cas = 1;
    scanf("%d", &t);
    while(t--)
    {
        int n, m;
        data1.clear();
        data2.clear();
        memset(vis, false, sizeof(vis));
        scanf("%d %d", &n, &m);
        int num;
        scanf("%d", &num);
        data1.push_back(0);
        data1.push_back(n);
        data2.push_back(0);
        data2.push_back(m);
        for(int i = 0; i < num; i++)
        {
            scanf("%d %d", &tx[i], &ty[i]);
            for(int d = -1; d <= 1; d++) {
                if(tx[i] + d >= 0 && tx[i] + d <= n) data1.push_back(tx[i] + d);
                if(ty[i] + d >= 0 && ty[i] + d <= m) data2.push_back(ty[i] + d);
            }
        }
        sort(data1.begin(), data1.end());
        sort(data2.begin(), data2.end());
        cntx = unique(data1.begin(), data1.end()) - data1.begin();
        cnty = unique(data2.begin(), data2.end()) - data2.begin();

        for(int i = 1; i < cntx; i++) {
            for(int j = 1; j < cnty; j++) {
                p[i][j] = (ll)(data1[i] - data1[i - 1]) * (data2[j] - data2[j - 1]);
     //               printf("%d %d %lld\n", i, j, p[i][j]);
            }
        }
        //p[i][j]表示(i, j)这个点表示的实际的点的个数

        for(int i = 0; i < num; i++) {
            int u = lower_bound(data1.begin(), data1.begin() + cntx, tx[i]) - data1.begin();
            int v = lower_bound(data2.begin(), data2.begin() + cnty, ty[i]) - data2.begin();
            vis[u][v] = true;
        }


//        for(int i = 1; i < cntx; i++) {
//            for(int j = 1; j < cnty; j++) {
//                printf("%d%c", vis[i][j], j == cnty - 1 ? '\n' : ' ');
//            }
//        }
//        printf("\n");

        ans.clear();
        for(int i = 1; i < cntx; i++) {
            for(int j = 1; j < cnty; j++) {
                if(!vis[i][j]) {
                    ans.push_back(bfs(i, j));
                }
            }
        }

        printf("Case #%d:\n", cas++);
        printf("%d\n", ans.size());
        sort(ans.begin(), ans.end());
        for(int i = 0; i < ans.size(); i++)
            printf("%lld%c", ans[i], i == ans.size() - 1 ? '\n' : ' ');
    }
}


猜你喜欢

转载自blog.csdn.net/deerly_/article/details/80170395