题意:N个不同颜色的矩形依次被堆放在一个宽A长B的矩形白纸上,求俯视视角中各种颜色所占的面积。
解题思路:
- 受HINT 1 启发,如果一个矩形与前面的矩形有重叠,那么就会将前面的矩形分割为几块,参见NOCOW(http://www.nocow.cn/index.php/USACO/rect1)中矩形切割部分。如下图阴影部分为矩形与前一个矩形的重叠部分。
- 用一个链表保存已有的矩形。每次堆放一个新的矩形input[5](五个元素分别为左下角坐标、右上角坐标,还有颜色)的时候,将其与这个链表中的每一个矩形cn[5]进行重叠检测。按照上图,重叠部分左下角坐标(llx, lly),右上角坐标(urx, ury)。那么
llx = max(input[0], cn[0]); lly = max(input[1], cn[1]); urx = min(input[2], cn[2]); ury = min(input[3], cn[3]);
- 如果urx <= llx 或者 ury <= lly,那么没有重叠部分,继续判断链表中下一个矩形
- 如果有重叠部分,那么首先删去这个被覆盖的矩形。然后按照图中标注的,将新生成的1, 2, 3, 4四个矩形加入链表。注意这4个矩形也许要按照第3步中的逻辑判断左下角和右上角的坐标是否正常,如果为正常则将其加入链表,否则不加入。
- 最后要将这个堆放在最上层的矩形加入链表。
- 重复2~5,直到最后一个矩形被堆叠上去。那么这个链表中的矩形就是最后俯视图的结果,链表中的矩形覆盖了整个A*B的坐标区域并且没有重叠。
- 遍历一遍链表,统计并输出最终结果
代码:
/*
ID: zc.rene1
LANG: C
PROG: rect1
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct rectangle
{
int llx, lly, urx, ury, color;
struct rectangle *next;
};
void CountColor(struct rectangle *head, int *color_count)
{
memset(color_count, 0, 1001*sizeof(int));
if (head == NULL)
{
return ;
}
head = head->next;
while (head != NULL)
{
color_count[head->color] += ((head->urx - head->llx) * (head->ury - head->lly));
head = head->next;
}
}
int max(int a, int b)
{
return a > b ? a : b;
}
int min(int a, int b)
{
return a < b ? a : b;
}
void InsertNode(int *input, struct rectangle *current)
{
struct rectangle *temp = (struct rectangle *)malloc(sizeof(struct rectangle));
memcpy(temp, input, 5*sizeof(int));
temp->next = current->next;
current->next = temp;
}
void DeleteNode(struct rectangle *prev, struct rectangle **current)
{
struct rectangle *temp = *current;
prev->next = (*current)->next;
*current = prev;
free(temp);
}
void InsertRectangle(int *input, struct rectangle *head)
{
struct rectangle *current = head;
struct rectangle *prev = NULL;
int cn[5];
int in[5];
int llx, lly, urx, ury;
while (current->next != NULL)
{
prev = current;
current = current->next;
memcpy(cn, current, 5*sizeof(int));
llx = max(input[0], cn[0]);
lly = max(input[1], cn[1]);
urx = min(input[2], cn[2]);
ury = min(input[3], cn[3]);
if ((urx <= llx) || (ury <= lly))
{
continue;
}
DeleteNode(prev, ¤t);
/*insert 1*/
if ((llx > cn[0]) && (cn[3] > lly))
{
in[0] = cn[0];
in[1] = lly;
in[2] = llx;
in[3] = cn[3];
in[4] = cn[4];
InsertNode(in, current);
}
/*insert 2*/
if ((cn[2] > llx) && (cn[3] > ury))
{
in[0] = llx;
in[1] = ury;
in[2] = cn[2];
in[3] = cn[3];
in[4] = cn[4];
InsertNode(in, current);
}
/*insert 3*/
if ((cn[2] > urx) && (ury > cn[1]))
{
in[0] = urx;
in[1] = cn[1];
in[2] = cn[2];
in[3] = ury;
in[4] = cn[4];
InsertNode(in, current);
}
/*insert 4*/
if ((urx > cn[0]) && (lly > cn[1]))
{
in[0] = cn[0];
in[1] = cn[1];
in[2] = urx;
in[3] = lly;
in[4] = cn[4];
InsertNode(in, current);
}
}
InsertNode(input, current);
}
int main(void)
{
FILE *fin, *fout;
int A, B, N;
int input[1001][5];
struct rectangle *tail = NULL;
struct rectangle *head = NULL;
int i, j, color, temp;
int color_count[1001];
fin = fopen("rect1.in", "r");
fout = fopen("rect1.out", "w");
/*get input*/
fscanf(fin, "%d %d %d", &A, &B, &N);
input[0][0] = 0;
input[0][1] = 0;
input[0][2] = A;
input[0][3] = B;
input[0][4] = 1;
for (i=1; i<=N; i++)
{
for (j=0; j<5; j++)
{
fscanf(fin, "%d", &input[i][j]);
}
}
/*begin to insert*/
head = (struct rectangle *)malloc(sizeof(struct rectangle));
for (i=0; i<=N; i++)
{
InsertRectangle(input[i], head);
}
/*get the count of each color*/
CountColor(head, color_count);
for (i=0; i<1001; i++)
{
if (color_count[i] != 0)
{
fprintf(fout, "%d %d\n", i, color_count[i]);
}
}
return 0;
}