代码:
/* ID: 改成你自己的 PROG: rect1 LANG: C */ #include <stdio.h> #include <stdlib.h> #define MAXCOORD 10000 #define MAXN 1000 typedef struct tagLinesTree {     int i, j, color;     struct tagLinesTree *leftchild;     struct tagLinesTree *rightchild; } LinesTree; typedef struct tagMatrix {     int llx, lly, urx, ury, color; } Matrix; int compare(const void *a, const void *b) {     return *(int *)a - *(int *)b; } void release_tree(LinesTree *t) {     if (t)     {         release_tree(t->leftchild);         release_tree(t->rightchild);         free(t);     } } void count_color(const int coord[], int color[], const int y_len, LinesTree *t) {     if (t)     {         if (t->color > 0)             color[t->color - 1] += y_len * (coord[t->j] - coord[t->i]);         else         {             count_color(coord, color, y_len, t->leftchild);             count_color(coord, color, y_len, t->rightchild);         }     } } void reset_tree(LinesTree *t) {     if (t)     {         reset_tree(t->leftchild);         reset_tree(t->rightchild);         t->color = 0;     } } void delete_duplicate(const int coord_src[], int *coord_len, int coord_dest[]) {     int i, len, count;     len = *coord_len;     coord_dest[0] = coord_src[0];     count = 0;     for (i = 1; i < len; ++i)     {         if (coord_dest[count] != coord_src[i])             coord_dest[++count] = coord_src[i];         else             --(*coord_len);     } } void build_tree(const int l, const int r, LinesTree *t) {     int k;     t->i = l;     t->j = r;     t->color = 0;     if (r - l > 1)     {         k = l + r;         t->leftchild = (LinesTree *)malloc(sizeof(LinesTree));         build_tree(l, k / 2, t->leftchild);         t->rightchild = (LinesTree *)malloc(sizeof(LinesTree));         build_tree(k / 2, r, t->rightchild);     }     else     {         t->leftchild = NULL;         t->rightchild = NULL;     } } void insert_tree(const int l, const int r, const int color, const int coord[], LinesTree *t) {     if (l <= coord[t->i] && coord[t->j] <= r)         t->color = color;     else     {         if (t->color > 0)         {             t->leftchild->color = t->color;             t->rightchild->color = t->color;             t->color = 0;         }         if (l < coord[(t->i + t->j) / 2])             insert_tree(l, r, color, coord, t->leftchild);         if (r > coord[(t->i + t->j) / 2])             insert_tree(l, r, color, coord, t->rightchild);     } } int main() {     FILE *fp_in;     FILE *fp_out;     int a, b, n, i, j;     int x_coord0[MAXCOORD], y_coord0[MAXCOORD];     int x_coord[MAXCOORD], y_coord[MAXCOORD];     int x_coord_idx = 0, y_coord_idx = 0;     LinesTree *root;     Matrix m[MAXN];     int color[MAXN] = { 0 };     fp_in = fopen("rect1.in", "r");     if (NULL == fp_in)         return EXIT_FAILURE;     fp_out = fopen("rect1.out", "w");     if (NULL == fp_out)         return EXIT_FAILURE;     fscanf(fp_in, "%d %d %d\n", &a, &b, &n);     for (i = 0; i < n; ++i)     {         fscanf(             fp_in,             "%d %d %d %d %d\n",             &m[i].llx, &m[i].lly, &m[i].urx, &m[i].ury, &m[i].color         );         x_coord0[x_coord_idx++] = m[i].llx;         y_coord0[y_coord_idx++] = m[i].lly;         x_coord0[x_coord_idx++] = m[i].urx;         y_coord0[y_coord_idx++] = m[i].ury;     }     qsort(x_coord0, x_coord_idx, sizeof(x_coord0[0]), compare);     qsort(y_coord0, y_coord_idx, sizeof(y_coord0[0]), compare);     delete_duplicate(x_coord0, &x_coord_idx, x_coord);     delete_duplicate(y_coord0, &y_coord_idx, y_coord);     root = (LinesTree *)malloc(sizeof(LinesTree));     build_tree(0, x_coord_idx - 1, root);     for (i = 0; i < y_coord_idx - 1; ++i)     {         for (j = 0; j < n; ++j)         {             if (m[j].lly <= y_coord[i] && y_coord[i + 1] <= m[j].ury)             {                 insert_tree(m[j].llx, m[j].urx, m[j].color, x_coord, root);             }         }         count_color(x_coord, color, y_coord[i + 1] - y_coord[i], root);         reset_tree(root);     }     release_tree(root);     // color 1     color[0] = 0;     for (i = 1; i < MAXN; ++i)     {         color[0] += color[i];   // other colors     }     color[0] = a * b - color[0];// total colors - other colors = color 1     for (i = 0; i < MAXN; ++i)     {         if (color[i])             fprintf(fp_out, "%d %d\n", i + 1, color[i]);     }     fclose(fp_in);     fclose(fp_out);     return EXIT_SUCCESS; }



用了离散化和线段树,好像是刚好200行。根据某些大牛的说法,算法的程序超过150行就算是失败的了。

BTW,请勿讨论代码风格问题。

  • 标 题: 答复
  • 作 者:luocong
  • 时 间:2005-06-06 16:46

按惯例好像应该先发一下题目的,补上:

代码:
Shaping Regions 形成的区域 译 by tim green   N个不同的颜色的不透明的长方形(1 <= N <= 1000)被放置在一张宽为A长为B的白纸上。 这些长方形被放置时,保证了它们的边于白纸的边缘平行。 所有的长方形都放置在白纸内,所以我们会看到不同形状的各种颜色。 坐标系统的原点(0,0)设在这张白纸的左下角,而坐标轴则平行于边缘。 PROGRAM NAME: rect1 INPUT FORMAT 每行输入的是放置长方形的方法。 第一行输入的是那个放在底的长方形(即白纸)。 第 1 行:       A , B 和 N, 由空格分开 (1 <=A, B<=10,000) 第 2 到N+1行:  为五个整数 llx, lly, urx, ury, color 这是一个长方形的左下角坐标,右上角坐标和颜色。 颜色 1和底部白纸的颜色相同。 SAMPLE INPUT (file rect1.in) 20 20 3 2 2 18 18 2 0 8 19 19 3 8 0 10 19 4 OUTPUT FORMAT 输出文件应该包含一个所有能被看到颜色连同该颜色的总面积的清单( 即使颜色的区域不是连续的),按color的增序顺序。 不要显示没有区域的颜色。 SAMPLE OUTPUT (file rect1.out) 1 91 2 84 3 187 4 38

  • 标 题: 答复
  • 作 者:luocong
  • 时 间:2005-06-06 17:02

解释一下思路:

1、读入各个矩形的llx, lly, urx, ury, color,然后离散化,再用delete_duplicate()生成一个新的离散化数组,这个新的数组是删除了重复坐标之后的。

2、用build_tree()创建x轴的线段树,其大小为x_coord_idx,也就是x轴离散化之后的坐标数。

3、在接下来的循环中,逐个判断每个矩形是否在当前y轴的范围内:

代码:
if (m[j].lly <= y_coord[i] && y_coord[i + 1] <= m[j].ury)


如果是的话,添加该矩形的x轴坐标到线段树中。

4、枚举完所有矩形后,用count_color()计算当前y轴的各个颜色值。

5、调用reset_tree()初始化线段树的颜色。

6、开始下一个y轴坐标,并重复过程3~5;直到y轴全部计算完毕。

7、扫尾,输出。

值得注意的是count_color()一定要用前序遍历,我刚开始写得头晕了,用了后序遍历,导致答案不正确,排了整整一天的错才发现的。

  • 标 题: 答复
  • 作 者:zmworm
  • 时 间:2005-06-07 22:04

花了一晚上的时间,我也写了一段代码,来凑凑热闹。用老罗给的例子测试,和他的结果一样,哈。不过我使用了个数组做白纸,挺吃内存的。另外输出的排序,直接使用了std(偷懒了)。程序用VC.net编译通过(用 VC6我想也应该没什么问题)

下面是C++代码

代码:
/* ShapingRegions.cpp ID: Zmworm[CCG] PROG: rect1 LANG: C++ */ #include "stdafx.h" #include <map> #include <vector> #include <fstream> #define MAX_SIZE  0x200 #define MAX_COORD MAX_SIZE * sizeof(int) * 8  //坐标最大值 16384 typedef struct tagMatrix {   int llx, lly, urx, ury, color; } Matrix; //一个矩形结构   Matrix BackRect;//白纸信息 static unsigned int  Coordinate [MAX_SIZE * MAX_COORD] ;//坐标数组 要浪费32M内存-__-|| std::map<int,int> ColorInfo;  //第一项为颜色类型,第二项为该颜色的数量 std::vector<Matrix> RectInfo; //保存从文件中读取的所有矩形信息 int init(); unsigned int check(int x,int y); //非零表示这个点已经被覆盖过了 int main() {   if (0 == init()) //读取元素,并进行检查     return -1;      int i,j,k;   i = (int)RectInfo.size() - 1;   ColorInfo[1] = BackRect.urx * BackRect.ury; //开始全是白色   for(i ;i >= 0 ;--i) //倒序读取     for(j = RectInfo[i].llx;j < RectInfo[i].urx ; ++j) //遍历一个矩形元素的x点       for(k = RectInfo[i].lly;k < RectInfo[i].ury ;++k) //遍历一个矩形元素的y点         if(0 == check(j,k))         {           ColorInfo[RectInfo[i].color]  += 1;  //如果该点没有占用,此颜色数目加1           ColorInfo[1] -=1;          //背景色减一,如果为0也可以跳出循环,并输出结果。         };   //输出结果   std::ofstream fout("rect1.out");   std::map<int, int>::iterator it;   for(it = ColorInfo.begin();it != ColorInfo.end();++it)     if( it->second != 0)       fout << it->first << " " << it->second << "\n";   fout.close();   return 1; } int init() {   std::ifstream fin("rect1.in");   if(fin.fail())     return -1;   int i = 0, count;   fin >> BackRect.urx >> BackRect.ury >> count;   if (BackRect.urx > MAX_COORD || BackRect.ury > MAX_COORD || 0 == BackRect.ury || 0 == BackRect.ury)     return -1; //检查白纸是否合法   Matrix eTemp;   while(!fin.eof() && i < count)   {     ++i;     fin >> eTemp.llx >> eTemp.lly >> eTemp.urx >> eTemp.ury >> eTemp.color;     if(eTemp.llx < eTemp.urx && eTemp.lly < eTemp.ury && eTemp.urx <= BackRect.urx && eTemp.ury <= BackRect.ury)       RectInfo.push_back(eTemp);//如果矩形数据合法,则加入这条信息   }   fin.close();   for (i =0;i< MAX_SIZE * MAX_COORD;++i)     Coordinate [i] = 0;//初始化白纸数组   return 1; } unsigned int check(int x,int y) {   int nResult;   int i = (y * BackRect.urx +x) / 32   int j = (y * BackRect.urx +x) % 32); //坐标转成白纸数组中的位置   unsigned int uMark = 1;   uMark  = uMark << j;   nResult = Coordinate[i] & uMark; //获得结果   Coordinate[i] |=  uMark ;//标记该点已经覆盖   return nResult; }

  • 标 题: 答复
  • 作 者:luocong
  • 时 间:2005-06-07 22:16

呵呵,第一个case过不了。。。因为USACO规定程序最多只能用16M内存。下面是运行结果:

TASK: rect1
LANG: C++

Compiling...
Compile: OK

Executing...
Execution error on machine 192.65.171.166: Your program (`rect1')
exited with signal #11 (segmentation violation [maybe caused by
accessing memory out of bounds, array indexing out of bounds, using a
bad pointer (failed open(), failed malloc), or going over the maximum
specified memory limit]) when presented with test case 1, shown below.
The program ran for 0 CPU seconds before the signal. 

----- Test Case 1 ------
20 20 3
2 2 18 18 2
0 8 19 19 3
8 0 10 19 4
----------------------------

  • 标 题: 答复
  • 作 者:zmworm
  • 时 间:2005-06-07 22:18

寒,没有看见“不要显示没有区域的颜色”
加上一句,呵呵“if( it->second != 0)”

  • 标 题: 答复
  • 作 者:zmworm
  • 时 间:2005-06-08 22:18

上一个代码用了棋盘标记,在数据很多的情况下,慢的要死。今天程序写了一个,方法就是切割矩形,我的做法是将一个矩形切割出成不多于四个小矩形。切割矩形真的好麻烦-__-||想了一白天才想出这种切割方法,可能还不是最快的方法。

代码:
┌─┬─┬─┐ │  │上│  │ │  ├─┤  │ │左│  │右│ │  ├─┤  │ │  │下│  │ └─┴─┴─┘




代码:
/* ShapingRegions2.cpp ID: Zmworm[CCG] PROG: rect1 LANG: C++ */ #include "stdafx.h" #include <fstream> #define MAX_COORD 10000 #define MAX_N 1000 #define MAX_COLOR MAX_N + 2 #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) typedef struct tagMatrix {   int llx, lly, urx, ury, color; } Matrix, *pMatrix; //一个矩形结构   Matrix BackRect ;//白纸信息 int RectDepth;//矩形的深度,为矩形总数量减一 static unsigned int  ColorInfo[MAX_COLOR];  //序号为颜色类型,第二项为该颜色的数量 Matrix  RectInfo[MAX_N] ; //保存从文件中读取的所有矩形信息 int init(); int DivRect(int nLayer, pMatrix matrix, int size); int main() {   if (0 == init()) //读取元素,并进行检查     return 1;      int i,j,k,temp;   ColorInfo[1] = BackRect.urx * BackRect.ury; //开始全是白色   for(i=0;i <= RectDepth;i++)//切割矩形   {     DivRect(i,&RectInfo[i],1);   }   //输出结果   std::ofstream fout("rect1.out");   for(i = 0;i < MAX_COLOR;++i)     if(   ColorInfo[i] != 0)       fout << i << " " << ColorInfo[i]<< "\n";   fout.close();   return 0; } int init() {   std::ifstream fin("rect1.in");   if(fin.fail())     return -1;   int i = 0;   fin >> BackRect.urx >> BackRect.ury >> RectDepth;   if (BackRect.urx > MAX_COORD || BackRect.ury > MAX_COORD || 0 == BackRect.ury || 0 == BackRect.ury)     return -1; //检查白纸是否合法   RectDepth -= 1;//深度为矩形数量减一,因为深度是从0开始的   Matrix eTemp;   while(!fin.eof() && i <= RectDepth)   {     fin >> eTemp.llx >> eTemp.lly >> eTemp.urx >> eTemp.ury >> eTemp.color;     if(eTemp.llx < eTemp.urx && eTemp.lly < eTemp.ury && eTemp.urx <= BackRect.urx && eTemp.ury <= BackRect.ury && eTemp.color < MAX_COLOR)       RectInfo[i] =eTemp;//如果矩形数据合法,则加入这条信息     ++i;   }   fin.close();   return 1; } int DivRect(int nLayer, pMatrix matrix, int size) {   int i,nAcreage;   if( RectDepth == nLayer)   {//如果到了最后一层,就输出结果     for(i = 0;i<size;++i)     {       nAcreage = (matrix[i].urx - matrix[i].llx) * (matrix[i].ury - matrix[i].lly);       ColorInfo[matrix->color] += nAcreage;//增加该区域颜色       ColorInfo[1] -= nAcreage;//从白色区域中去除     }     return 1;   }   for(i = 0; i<size; ++i)   {     int ax =matrix[i].llx;//要切割的矩形     int ay =matrix[i].lly;     int bx =matrix[i].urx;     int by =matrix[i].ury;     int Ax =RectInfo[nLayer+1].llx;//下一层的矩形     int Ay =RectInfo[nLayer+1].lly;     int Bx =RectInfo[nLayer+1].urx;     int By =RectInfo[nLayer+1].ury;     if   (bx < Ax || ax > Bx || by <Ay || ay > By)     {//两矩形没有相交       DivRect(nLayer+1,matrix+i,1);     }     else     {//处理两矩形相交时的情况,就是把矩形分成四部分       pMatrix pDivRect1 = new Matrix[4];       int j = 0;       if (by > By)//上区       {         pDivRect1[j].color = matrix[0].color;         pDivRect1[j].llx = max(ax,Ax);         pDivRect1[j].lly = By;         pDivRect1[j].urx = min(bx,Bx);         pDivRect1[j].ury = by;         ++j;             }       if(Ay > ay)//下区       {         pDivRect1[j].color = matrix[0].color;         pDivRect1[j].llx = max(ax,Ax);         pDivRect1[j].lly = ay;         pDivRect1[j].urx = min(bx,Bx);         pDivRect1[j].ury = Ay;         ++j;               }       if(ax < Ax)//左区       {         pDivRect1[j].color = matrix[0].color;         pDivRect1[j].llx = ax;         pDivRect1[j].lly = ay;         pDivRect1[j].urx = Ax;         pDivRect1[j].ury = by;         ++j;       }       if(Bx < bx)//右区       {         pDivRect1[j].color = matrix[0].color;         pDivRect1[j].llx = Bx;         pDivRect1[j].lly = ay;         pDivRect1[j].urx = bx;         pDivRect1[j].ury = by;         ++j;       }       if(j)//如果切割出矩形,则进入下一层       DivRect(nLayer+1,pDivRect1,j);       delete pDivRect1;     }   }   return 1; }