HDU5925 coconut 离散化处理

Coconuts

Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 681    Accepted Submission(s): 193

Problem Description

TanBig, a friend of Mr. Frog, likes eating very much, so he always has dreams about eating. One day, TanBig dreams of a field of coconuts, and the field looks like a large chessboard which has R rows and C columns. In every cell of the field, there is one coconut. Unfortunately, some of the coconuts have gone bad. For sake of his health, TanBig will eat the coconuts following the rule that he can only eat good coconuts and can only eat a connected component of good coconuts one time(you can consider the bad coconuts as barriers, and the good coconuts are 4-connected, which means one coconut in cell (x, y) is connected to (x - 1, y), (x + 1, y), (x, y + 1), (x, y - 1).
Now TanBig wants to know how many times he needs to eat all the good coconuts in the field, and how many coconuts he would eat each time(the area of each 4-connected component).

Input

The first line contains apositiveinteger T(T≤10) which denotes the test cases. T test cases begin from the second line. In every test case, the first line contains two integers R and C, 0<R,C≤109 the second line contains an integer n, the number of bad coconuts, 0≤n≤200 from the third line, there comes n lines, each line contains two integers, xi and yi, which means in cell(xi,yi), there is a bad coconut.
It is guaranteed that in the input data, the first row and the last row will not have bad coconuts at the same time, the first column and the last column will not have bad coconuts at the same time.

Output

For each test case, output "Case #x:" in the first line, where x denotes the number of test case, one integer k in the second line, denoting the number of times TanBig needs, in the third line, k integers denoting the number of coconuts he would eat each time, you should output them in increasing order.

Sample Input

2 3 3 2 1 2 2 1 3 3 1 2 2

Sample Output

Case #1: 2 1 6 Case #2: 1 8

Source

2016CCPC东北地区大学生程序设计竞赛 - 重现赛

Recommend

wange2014   |   We have carefully selected several similar problems for you:  6014 6013 6012 6011 6010

——————————————————————正文————————————————————————————————

  嘛,比赛的时候完全没看这道题,所以也没来得及想这道。

  赛后补题的时候说是要用离散化,但是不得不说,离散化这个概念和递归差不多,都是非常宽泛的,所以思考了一会发现还是不会详细解法。

  然后看了下ac代码,嗯现在以自己的理解说一下。

  从这个题目中,我们可以看到,1,障碍点很少,只有200个 2 空白的区域很大。

  那么我们是否可以将原来的图压缩,同时记录压缩前的值,同时维持着障碍块之间的关系不变的情况下用dfs搜索压缩完毕以后的图呢?

  这就是离散化的意义。

  这里我们要离散的是X轴和Y轴,将障碍点输入以后,分x轴,y轴数组存储,然后再进行排序,那么如果相邻的两个点之间的距离大于1,那就说明在原图上这块地方是一块矩形且其宽为两点之差-1的空白区域,那么这块很明显就是可以压缩的地方了,于是我们就把他压缩并进入新的图。

  在实践中还会遇到一个问题,某轴上有重复的多个点,很明显在新图上他们是重叠的,那么可以暂时不予考虑,因为这个新图的目录值和原有的目录值的映射是会保存的,这也就保证的障碍块的位置关系没有改变。

  那么我们上面是利用一个点和前一个点的距离来判断是否有可压缩的点,既然如此边界处理要做好,所以0和边界都要输入到新图的x轴,y轴目录中。

  然后dfs的时候调用压缩的数据就好了(其实是懒得讲了,用代码说话吧

  反反复复ac了3遍,最后一遍是用自己惯用的风格写的(花式vector,请勿学习)

——————————————CODE———————————————————

#include<iostream> 
#include<cstdio> 
#include<cmath> 
#include<algorithm> 
#include<cstring> 
#include<map>
#include<vector>
#include<string>
#include<queue>
#include<deque>
#define ll long long
#define mem(x,y) memset(x,y,sizeof(x))
#define _size 500
#define file_in freopen("input.txt","r",stdin)
using namespace std;
const int maxn = 100010;
struct point {
    ll i;
    ll j;
};
ll vst[_size][_size];
vector<ll>ni, nj;
ll sum;
int di[] = { 0,0,-1,1 };
int dj[] = { 1,-1,0,0 };
void dfs(int i, int j)
{
    if (vst[i][j] || i >= ni.size() || i < 0 || j >= nj.size() || j < 0)return;
    sum +=(ll) ni[i] * (ll)nj[j];
    vst[i][j] = 1;
    for (int f = 0; f < 4; f++)
    {
        dfs(i + di[f], j + dj[f]);
    }
}
int main()
{
    int casei;
    scanf("%d", &casei);
    for (int i = 0; i < casei; i++)
    {
        ll ri, cj;
        scanf("%lld %lld", &cj, &ri);
        ll q;
        scanf("%lld", &q);
        vector<point>poi(q);
        for (int i = 0; i < q; i++)
        {
            scanf("%lld %lld", &poi[i].j, &poi[i].i);
        }
        printf("Case #%d:\n", i + 1);
        vector<ll>ii;
        vector<ll>jj;
        ii.push_back(0);
        ii.push_back(ri);
        jj.push_back(0);
        jj.push_back(cj);
        for (ll i = 0; i < q; i++)
        {
            ii.push_back(poi[i].i);
            jj.push_back(poi[i].j);
        }
        sort(ii.begin(), ii.end());
        sort(jj.begin(), jj.end());
        ll numi = unique(ii.begin(), ii.end()) - ii.begin();
        ll numj = unique(jj.begin(), jj.end()) - jj.begin();
        ni.clear();
        nj.clear();
        map<ll, ll>mi, mj;
        for (ll i = 1; i < numi; i++)
        {
            if (ii[i] - ii[i - 1] > 1)ni.push_back(ii[i] - ii[i - 1] - 1);
            ni.push_back(1);
            mi[ii[i]] = ni.size()-1 ;
        }
        for (ll j = 1; j < numj; j++)
        {
            if (jj[j] - jj[j - 1] > 1)nj.push_back(jj[j] - jj[j - 1] - 1);
            nj.push_back(1);
            mj[jj[j]] = nj.size()-1;
        }
        mem(vst, 0);
        for (int i = 0; i < q; i++)
        {
            vst[mi[poi[i].i]][mj[poi[i].j]] = 1;
        }
        vector<ll>ans;
        for (int i = 0; i < ni.size(); i++)
        {
            for (int j = 0; j < nj.size(); j++)
            {
                sum = 0;
                if (!vst[i][j])
                    dfs(i, j);
                if(sum)
                    ans.push_back(sum);
            }
        }
        sort(ans.begin(), ans.end());
        cout << ans.size() << endl;
        for (int i = 0; i < ans.size(); i++)
        {
            if (i)printf(" %lld", ans[i]);
            else printf("%lld", ans[i]);
        }
        printf("\n");
    }
}
/*Sample Input
2

3 3
2
1 2
2 1

3 3
1
2 2
Sample Output
Case #1:
2
1 6
Case #2:
1
8*/

转载于:https://www.cnblogs.com/stultus/p/6393444.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值