1033 - Merging Maps

本文介绍了一种用于合并多个地图数据的算法。该算法通过对比不同地图之间的特征匹配度来确定最佳的地图叠加方式,最终生成一张完整的大型地图。文章详细解释了地图特征识别、地图配准、评分标准以及地图合并的具体步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Pictures taken from an airplane or satellite of an ar ea to be mapped are often of sufficiently high resolution to uniquely identify major features. Since a single picture can cover only a small portion of the earth, mapping larger areas requires taking pictures of smaller overlapping areas, and then merging these to produce a map of a larger area.

For this problem you are given several maps of rectangular areas, each represented as an array of single- character cells. A cell contains an uppercase alphabetic character (`A' to `Z') if its corresponding area contains an identifiable major feature. Different letters correspond to different features, but the same major feature (such as a road) may be identified in multiple cells. A cell contains a hyphen (`-') if no identifiable feature is located in the cell area. Merging two maps means overlaying them so that one or more common major features are aligned. A cell containing a major feature in one map can be overlaid with a cell not containing a major feature in the other. However, different major features (with diff erent letters) cannot be overlaid in the same cell.

 

          --A-C     C----     C----     ----D     -D--C
          ----D     D---F     -----     -E--B     ----G
          ----B     B----     B-A-C     -----     ----B
    Map #   1         2         3         4         5

Consider the five 3-row, 5-column maps shown above. The rightmost column of map 1 perfectly matches the leftmost column of map 2, so those maps could be overlaid to yield a 3-row, 9-column map. But map 1 could also overlay map 3 as well, since the C and B features in the rightmost column of map 1 match those in the leftmost column of map 3; the D does not perfectly match the `-' in the center of the column, but there is no conflict. In a similar manner, the top row of map 1 could also overlay the bottom row of map 3.

The ``score" of a pair of maps indicates the extent to which the two maps match. The score of an overlay of a pair of maps is the number of cells containing major features that coincide in the overlay that gives the best match. The score for the map pair is the maximum score for the possible overlays of the maps. Thus, the score for a pair of maps each having 3 rows and 5 columns must be in the range 0 to 15.

An ``offset" is a pair of integers (rc) that specifies how two maps, a and b, are overlaid. The value of rgives the offset of rows in b relative to rows in a; similarly, c gives the offset of columns in b relative to columns in a. For example, the overlay of map 1 and map 2 shown above has the offset (0,4) and a score of 3. The two overlays of map 1 and map 3 yielding scores of 2 have offsets of (0,4) and (-2,0).

The following steps describe how to merge a sequence of maps:

 

  1. Merge the pair of maps in the sequence that yield the highest positive score (resolving ties by choos ing pair that has the map with the lowest sequence number).
  2. Remove the maps that were merged from the sequence.
  3. Add the resulting merged map to the sequence, giving it the next larger sequence number.

In the example above, maps 1 and 2 would be merged to produce map 6, and maps 1 and 2 would be removed from the sequence. Steps 1, 2 and 3 are repeated until only a single map remains in the sequence, or until none of the maps in the sequence can be merged (that is, until the overlay score for each possible map pair is zero).

If two maps can be merged in several ways to yield the same score, then merge them using the smallest row offset. If the result is still ambiguous, use the smallest row offset and the smallest column offset.

 

Input 

The input will contain one or more sets of data, each containing between 2 and 10 maps. Each set of data begins with an integer specifying the number of maps in the sequence. The maps follow, each beginning with a line containing two integers  NR  and  NC  (   1$ \le$NRNC$ \le$10 ) that specify the number of rows and columns in the map that immediately follows on the next  NR  lines. The first  NC  characters on each of these  NR  lines are the map data, and any trailing characters on such lines are to be ignored.

Input for the last test case is followed by a line consisting of the number 0.

 

Output 

For each set of data, display the input case number (1, 2, ...) and the merged maps, each identified with its sequence number and enclosed by a border. The output should be formatted as shown in the samples below. No merged map will have more than 70 columns.

 

Sample Input 

5
3 5
--A-C
----D
----B
3 5
C----
D---F
B----
3 5
C----
-----
B-A-C
3 5
----D
-E--B
-----
3 5
-D--C
----G
----B
2
3 5
----A
----B
----C
3 5
A----
B----
D----
0

 

Sample Output 

Case 1
    MAP 9:
    +-------------+
    |-D--C--------|
    |----G--------|
    |----B-A-C----|
    |--------D---F|
    |-----E--B----|
    |-------------|
    +-------------+

Case 2
    MAP 1:
    +-----+
    |----A|
    |----B|
    |----C|
    +-----+

    MAP 2:
    +-----+
    |A----|
    |B----|
    |D----|
    +-----+

 




 

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct MAPS
{
	int n,m;
	char feature[110][110];
};
struct Merge
{
	int score,r,c;
};
char s[2000];
int cases,n,i,j,k,sum,max,x,y;
MAPS map[100];
Merge merge[100][100];
bool sign[100];
int calc(char a,char b)
{
	if(a=='-') return 0;
	if(b=='-') return 0;
	if(a==b) return 1;
	else return -10000;
}

int Max(int a,int b)
{
	if(a>b) return a;
	else return b;
}

int Min(int a,int b)
{
	if(a>b) return b;
	else return a;
}

Merge Try(int x,int y)
{
	int r,c,i,j,k,score,x1,y1,x2,y2;
	Merge tmp;
	tmp.score=0;
	for(r=-map[y].n+1;r<map[x].n;r++)
		for(c=-map[y].m+1;c<map[x].m;c++)
		{
			x1=Max(0,r);y1=Max(0,c);
			x2=Min(map[x].n,map[y].n+r);y2=Min(map[x].m,map[y].m+c);
			score=0;
			for(i=x1;i<x2;i++)
				for(j=y1;j<y2;j++)
					score+=calc(map[x].feature[i][j],map[y].feature[i-r][j-c]);
			if(score>tmp.score)
			{
				tmp.score=score;
				tmp.r=r;
				tmp.c=c;
			}
		}
	return tmp;
}

void add_map(int x,int y,int z)
{
	int i,j,k,Dx,Dy;
	Dx=Max(-merge[x][y].r,0);Dy=Max(-merge[x][y].c,0);
	map[z].n=Max(map[x].n,map[y].n+merge[x][y].r)+Dx;
	map[z].m=Max(map[x].m,map[y].m+merge[x][y].c)+Dy;
	for(i=0;i<map[z].n;i++)
		for(j=0;j<map[z].m;j++)
			map[z].feature[i][j]='-';
	for(i=0;i<map[x].n;i++)
		for(j=0;j<map[x].m;j++)
			map[z].feature[i+Dx][j+Dy]=map[x].feature[i][j];
	Dx+=merge[x][y].r;Dy+=merge[x][y].c;
	for(i=0;i<map[y].n;i++)
		for(j=0;j<map[y].m;j++)
			if(map[y].feature[i][j]!='-')
				map[z].feature[i+Dx][j+Dy]=map[y].feature[i][j];
}

int main()
{
	for(cases=1;;cases++)
	{
		scanf("%d",&n);
		if(n==0) break;
		for(i=1;i<=n;i++)
		{
			scanf("%d %d",&map[i].n,&map[i].m);
			for(j=0;j<map[i].n;j++)
			{
				scanf("%s",s);
				for(k=0;k<map[i].m;k++)
					map[i].feature[j][k]=s[k];
			}
		}
		for(i=1;i<=n;i++)
			for(j=i+1;j<=n;j++)
				merge[i][j]=Try(i,j);
		memset(sign,1,sizeof(sign));
		while(1)
		{
			max=0;
			for(i=1;i<=n;i++) if(sign[i])
				for(j=i+1;j<=n;j++) if(sign[j])
					if(merge[i][j].score>max)
					{
						max=merge[i][j].score;
						x=i;y=j;
					}
			if(max==0)
				break;

			sign[x]=sign[y]=0;
			n++;
			add_map(x,y,n);
			for(i=1;i<n;i++)
				if(sign[i])
					merge[i][n]=Try(i,n);
		}
		if(cases>1)
			printf("\n");
		printf("Case %d\n",cases);
		x=0;
		for(i=1;i<=n;i++)
			if(sign[i])
			{
				if(x)
					printf("\n");
				x++;
				printf("    MAP %d:\n",i);
				printf("    +");
				for(j=0;j<map[i].m;j++)
					printf("-");
				printf("+\n");
				for(j=0;j<map[i].n;j++)
				{
					printf("    |");
					for(k=0;k<map[i].m;k++)
						printf("%c",map[i].feature[j][k]);
					printf("|\n");
				}
				printf("    +");
				for(j=1;j<=map[i].m;j++)
					printf("-");
				printf("+\n");
			}
	}
	return 0;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值