Codeforces 335D Rectangles and Square 暴力 + DP

来源:互联网 发布:淘宝大格子代码 编辑:程序博客网 时间:2024/06/04 23:22

题目大意:

给定n个矩形(1 <= n <= 10^5), 每个矩形的顶点都在整点上, 且矩形两两重叠面积是0(最多只有边重合)

每个矩形给出其左下角坐标和右上角坐标, 坐标(x, y)满足(0 <= x <= 3000, 0 <= y <= 3000)

求是否存在一个正方形,这个正方形刚好是这n个矩形中的某些所拼凑起来的,(拼凑不能有缝隙), 如果有就找出这样的一组矩形, 否则输出NO


大致思路:

这题感觉dp还是有点巧妙的, 再就是巴黎枚举每个矩形的左下角是否是要找的正方形的左下角, 利用预处理好的数组来判断是否能继续增加边长

很巧妙吧还是感觉这种做法, 细节都写在代码注释里了


代码如下:

Result  :  Accepted     Memory  :  179908 KB     Time  :  872 ms

/* * Author: Gatevin * Created Time:  2015/3/4 14:41:14 * File Name: Kotori_Itsuka.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<ctime>#include<iomanip>using namespace std;const double eps(1e-8);typedef long long lint;/* * 用cov[i][j]表示在所有的格子当中在矩形(1, 1)至矩形(i, j)中被覆盖的正方形的个数 * covl[i][j]表示第i列(横坐标为i)中从纵坐标1到j中对应的矩形被覆盖的个数且作为某个矩形的左边界 * covr[i][j]对应右边界, covd[i][j]下边界, covu[i][j]上边界 * (x1[i], y1[i], x2[i], y2[i])对应矩形i的左下角和右上角 * 每次枚举矩形n的左下角作为最后形成正方形的左下角, 然后枚举边长len利用cov系列数组判断是否合适 */int n;int cov[3010][3010], covl[3010][3010], covr[3010][3010], covd[3010][3010], covu[3010][3010];int x1[100010], y1[100010], x2[100010], y2[100010];vector<int> ans;int main(){    scanf("%d", &n);    for(int i = 1; i <= n; i++)        scanf("%d %d %d %d", x1 + i, y1 + i, x2 + i, y2 + i);    for(int i = 1; i <= n; i++)    {        for(int x = x1[i] + 1; x <= x2[i]; x++)            for(int y = y1[i] + 1; y <= y2[i]; y++)                cov[x][y] = 1;        for(int x = x1[i] + 1; x <= x2[i]; x++)            covd[x][y1[i] + 1] = covu[x][y2[i]] = 1;        for(int y = y1[i] + 1; y <= y2[i]; y++)            covl[x1[i] + 1][y] = covr[x2[i]][y] = 1;    }    for(int i = 1; i <= 3000; i++)        for(int j = 1; j <= 3000; j++)        {            cov[i][j] += cov[i - 1][j] + cov[i][j - 1] - cov[i - 1][j - 1];            covd[i][j] += covd[i - 1][j];            covu[i][j] += covu[i - 1][j];            covl[i][j] += covl[i][j - 1];            covr[i][j] += covr[i][j - 1];        }    for(int i = 1; i <= n; i++)//枚举矩形的左下角    {        int len = 1, x = x1[i], y = y1[i];//len表示边长        for(; covl[x + 1][y + len] - covl[x + 1][y] == len && covd[x + len][y + 1] - covd[x][y + 1] == len; len++)        {            if(cov[x + len][y + len] - cov[x][y + len] - cov[x + len][y] + cov[x][y] != len*len) break;            if(covu[x + len][y + len] - covu[x][y + len] == len && covr[x + len][y + len] - covr[x + len][y] == len)            {                for(int j = 1; j <= n; j++)//只要左下角在这个范围, 按照cov数组的保证和题意矩形一定都在这个范围                    if(x1[j] >= x && x1[j] < x + len && y1[j] >= y && y1[j] < y + len)                        ans.push_back(j);                printf("YES %d\n", (int)ans.size());                for(unsigned int j = 0; j < ans.size(); j++)                    printf("%d ", ans[j]);                return 0;            }        }    }    printf("NO\n");    return 0;}


0 0
原创粉丝点击