首页
社区
课程
招聘
Shaping Regions源代码
2005-6-6 16:41 15646

Shaping Regions源代码

2005-6-6 16:41
15646
/*
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,请勿讨论代码风格问题。

阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!

收藏
点赞7
打赏
分享
最新回复 (16)
雪    币: 1593
活跃值: (741)
能力值: ( LV13,RANK:370 )
在线值:
发帖
回帖
粉丝
luocong 9 2005-6-6 16:46
2
0
按惯例好像应该先发一下题目的,补上:

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
雪    币: 515
活跃值: (1223)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
RoBa 16 2005-6-6 16:50
3
0
学习

我写过230行的,汗。。。

我听到的说法是,大牛能够在比赛中敲出二百多行的代码,仍然面不改色,然后一次编译通过,然后一次提交就AC
雪    币: 1593
活跃值: (741)
能力值: ( LV13,RANK:370 )
在线值:
发帖
回帖
粉丝
luocong 9 2005-6-6 17:02
4
0
解释一下思路:

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()一定要用前序遍历,我刚开始写得头晕了,用了后序遍历,导致答案不正确,排了整整一天的错才发现的。
雪    币: 1593
活跃值: (741)
能力值: ( LV13,RANK:370 )
在线值:
发帖
回帖
粉丝
luocong 9 2005-6-6 17:03
5
0
最初由 RoBa 发布
学习

我写过230行的,汗。。。

我听到的说法是,大牛能够在比赛中敲出二百多行的代码,仍然面不改色,然后一次编译通过,然后一次提交就AC


寒就一个字,我要说 2 * N 次!
雪    币: 288
活跃值: (70)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
hejiwen 2 2005-6-6 17:09
6
0
支持你们!
雪    币: 1223
活跃值: (469)
能力值: (RANK:460 )
在线值:
发帖
回帖
粉丝
monkeycz 11 2005-6-6 17:59
7
0
偶记得2000年NOI某赛区省赛,有一牛人,从看到题目就开始写代码,目不斜视,一口气全部搞定,编译,通过,交卷,走人……

雪    币: 221
活跃值: (137)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
xsy3660 4 2005-6-7 08:00
8
0
看不懂,也要顶一下。高人出手确实不凡
雪    币: 339
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
nbw 24 2005-6-7 08:58
9
0
顶阿。。
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
北极星2003 25 2005-6-7 15:46
10
0
中午的时候把程序打印出来。
现在大致看懂程序代码的意思,不过对于这种算法的思路脑子还是有点混乱。
继续学习。。。。

不过老罗的程序中变量定义的有点混乱哦,再加上没有注释。。。。
希望老罗下次出算法的时候能给点注释,这样稍微容易点
雪    币: 1593
活跃值: (741)
能力值: ( LV13,RANK:370 )
在线值:
发帖
回帖
粉丝
luocong 9 2005-6-7 20:40
11
0
这道题首先要看懂陈宏的论文就可以,线段树只是一个简单的平衡树而已。弄懂算法才素王道。
雪    币: 5143
活跃值: (363)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
zmworm 4 2005-6-7 22:04
12
0
花了一晚上的时间,我也写了一段代码,来凑凑热闹。用老罗给的例子测试,和他的结果一样,哈。不过我使用了个数组做白纸,挺吃内存的。另外输出的排序,直接使用了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;
}
雪    币: 1593
活跃值: (741)
能力值: ( LV13,RANK:370 )
在线值:
发帖
回帖
粉丝
luocong 9 2005-6-7 22:16
13
0
呵呵,第一个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
----------------------------
雪    币: 5143
活跃值: (363)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
zmworm 4 2005-6-7 22:18
14
0
寒,没有看见“不要显示没有区域的颜色”
加上一句,呵呵“if( it->second != 0)”
雪    币: 5143
活跃值: (363)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
zmworm 4 2005-6-7 22:19
15
0
最初由 luocong 发布
呵呵,第一个case过不了。。。因为USACO规定程序最多只能用16M内存。下面是运行结果:

TASK: rect1
LANG: C++

........


还有这么一说?
雪    币: 515
活跃值: (1223)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
RoBa 16 2005-6-7 22:20
16
0
USACO果然好,哪个CASE过不去居然都能看到.
雪    币: 5143
活跃值: (363)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
zmworm 4 2005-6-8 22:18
17
0
上一个代码用了棋盘标记,在数据很多的情况下,慢的要死。今天程序写了一个,方法就是切割矩形,我的做法是将一个矩形切割出成不多于四个小矩形。切割矩形真的好麻烦-__-||想了一白天才想出这种切割方法,可能还不是最快的方法。
┌─┬─┬─┐
│  │上│  │
│  ├─┤  │
│左│  │右│
│  ├─┤  │
│  │下│  │
└─┴─┴─┘


/* 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;
}
游客
登录 | 注册 方可回帖
返回