Spreadsheet Tracking

原题及翻译

Data in spreadsheets are stored in cells, which are organized in rows ® and columns ©.
电子表格中的数据存储在单元格中,单元格按行(R)和列(C)组织。
Some operations on spreadsheets can be applied to single cells (r, c), while others can be applied to entire rows or columns.
电子表格上的某些操作可以应用于单个单元格(R、C),而其他操作可以应用于整个行或列。
Typical cell operations include inserting and deleting rows or columns and exchanging cell contents.
典型的单元操作包括插入和删除行或列以及交换单元内容。
Some spreadsheets allow users to mark collections of rows or columns for deletion, so the entire collection can be deleted at once.
有些电子表格允许用户标记要删除的行或列集合,因此可以一次删除整个集合。
Some (unusual) spreadsheets allow users to mark collections of rows or columns for insertions too.
一些(不寻常的)电子表格也允许用户标记行或列的集合进行插入。
Issuing an insertion command results in new rows or columns being inserted before each of the marked rows or columns.
发出插入命令将导致在每个标记的行或列之前插入新的行或列。
Suppose, for example, the user marks rows 1 and 5 of the spreadsheet on the left for deletion.
例如,假设用户将电子表格左侧的第1行和第5行标记为删除。
The spreadsheet then shrinks to the one on the right.
然后电子表格缩小到右边的那个。
在这里插入图片描述
If the user subsequently marks columns 3, 6, 7, and 9 for deletion, the spreadsheet shrinks to this.
如果用户随后将第3、6、7和9列标记为删除,则电子表格将缩小到此列。
在这里插入图片描述
If the user marks rows 2, 3 and 5 for insertion, the spreadsheet grows to the one on the left.
如果用户将第2、3和5行标记为插入,则电子表格将变为左侧的一行。
If the user then marks column 3 for insertion, the spreadsheet grows to the one in the middle.
如果用户随后将第3列标记为插入,则电子表格将增长到中间的一列。
Finally, if the user exchanges the contents of cell (1,2) and cell (6,5), the spreadsheet looks like the one on the right.
最后,如果用户交换单元格(1,2)和单元格(6,5)的内容,那么电子表格看起来就像右边的一样。
在这里插入图片描述
You must write tracking software that determines the final location of data in spreadsheets that result from row, column, and exchange operations similar to the ones illustrated here.
您必须编写跟踪软件来确定数据在电子表格中的最终位置,这些位置是由行、列和交换操作产生的,与此处所示类似。

Input

输入
The input consists of a sequence of spreadsheets, operations on those spreadsheets, and queries about them.
输入由一系列电子表格、对这些电子表格的操作以及有关它们的查询组成。
Each spreadsheet definition begins with a pair of integers specifying its initial number of rows® and columns ©, followed by an integer specifying the number (n) of spreadsheet operations.
每个电子表格定义以一对整数开始,指定其初始行数(r)和列数(c),然后是一个整数,指定电子表格操作的数目(n)。
Row and column labeling begins with 1.
行和列标签以1开头。
The maximum number of rows or columns of each spreadsheet is limited to 50.
每个电子表格的最大行数或列数限制为50。
The following n lines specify the desired operations.
以下n行指定所需的操作。
An operation to exchange the contents of cell (r1, c1) with the contents of cell (r2,c2) is given by:EX r1 c1 r2 c2
将单元(R1,C1)的内容物与单元(R2,C2)的内容物交换的操作由:ex r1 c1 r2 c2给出。
The four insert and delete commands—DC (delete columns), DR (delete rows), IC (insert columns), and IR (insert rows) are given by:< command > A x1 x2 . . . xA
四个插入和删除命令dc(删除列)、dr(删除行)、ic(插入列)和ir(插入行)由:a x1 x2给出。…XA
where < command > is one of the four commands; A is a positive integer less than 10, and x1, . . . , xA are the labels of the columns or rows to be deleted or inserted before.
其中是四个命令之一;a是小于10的正整数,x1,。…,xa是要删除或插入的列或行的标签。
For each insert and delete command, the order of the rows or columns in the command has no significance.
对于每个插入和删除命令,命令中的行或列的顺序没有意义。
Within a single delete or insert command, labels will be unique.
在单个删除或插入命令中,标签将是唯一的。
The operations are followed by an integer which is the number of queries for the spreadsheet.
操作后面是一个整数,它是电子表格的查询数。
Each query consists of positive integers r and c, representing the row and column number of a cell in the original spreadsheet.
每个查询由正整数r和c组成,表示原始电子表格中单元格的行和列号。
For each query, your program must determine the current location of the data that was originally in cell (r, c).
对于每个查询,程序必须确定原始数据在单元格(r,c)中的当前位置。
The end of input is indicated by a row consisting of a pair of zeros for the spreadsheet dimensions.
输入的结尾由一行表示,该行由一对用于电子表格维度的零组成。

Output

输出
For each spreadsheet, your program must output its sequence number (starting at 1).
对于每个电子表格,程序必须输出其序列号(从1开始)。
For each query, your program must output the original cell location followed by the final location of the data or the word ‘GONE’ if the contents of the original cell location were destroyed as a result of the operations.
对于每个查询,如果操作导致原始单元格位置的内容被破坏,则程序必须输出原始单元格位置,后跟数据的最终位置或单词“Gone”。
Separate output from different spreadsheets with a blank line.
用空行将不同电子表格的输出分开。
The data file will not contain a sequence of commands that will cause the spreadsheet to exceed the maximum size.
数据文件将不包含将导致电子表格超过最大大小的命令序列。
在这里插入图片描述

思路

最直接的思路就是首先模拟操作,算出最后的电子表格,然后在每次查询时直接在电子表格中找到所求的单元格。

基本思路就是利用三个二维数组和一个一维数组进行转换:

int r,c,n,d[maxd][maxd],d2[maxd][maxd],ans[maxd][maxd],cols[maxd];
//r——行数,c——列数,n——操作数
//d用于存储最初的电子表格,d2用于中间进行操作的电子表格,ans用于存储最终的电子表格

代码分析

#include <stdio.h>
#include <string.h>
#define maxd 100
#define BIG 10000
int r,c,n,d[maxd][maxd],d2[maxd][maxd],ans[maxd][maxd],cols[maxd];
//r——行数,c——列数,n——操作数
//d用于存储最初的电子表格,d2用于中间进行操作的电子表格,ans用于存储最终的电子表格
void copy(char type,int p,int q)
{
	if(type=='R')
	{//如果是行
		for(int i=1;i<=c;i++)
		{//让d第p行的每一列等于d2第q行的每一列
			d[p][i]=d2[q][i];
		}
	}
	else
	{//如果是列
		for(int i=1;i<=r;i++)
		{//让d第p列的每一行等于d2第q列的每一行
			d[i][p]=d2[i][q];
		}
	}
}
void del(char type)
{
	memcpy(d2,d,sizeof(d));
	//从d内存地址的起始位置开始拷贝整个d到d2内存地址中。
	int cnt=type=='R'?r:c,cnt2=0;
	//确定删除的是行/列?
	for(int i=1;i<=cnt;i++)
	{
		if(!cols[i]) copy(type,++cnt2,i);
		//如果该行/列为0,拷贝
	}
	if(type=='R') r=cnt2;
	//如果是行操作,记录新的行总数
	else c=cnt2;
	//如果是列操作,记录新的列总数
}
void ins(char type)
{
	memcpy(d2,d,sizeof(d));
	int cnt=type=='R'?r:c,cnt2=0;
	for(int i=1;i<=cnt;i++)
	{
		if(cols[i]) copy(type,++cnt2,0);
		copy(type,++cnt2,i);
	}
	if(type=='R') r=cnt2;
	else c=cnt2;
}
int main ()
{
	int r1,c1,r2,c2,q,kase=0;
	//kase用于输出标号
	char cmd[10];
	memset(d,0,sizeof(d));
	while(scanf("%d%d%d",&r,&c,&n)==3&&r)
	{//读入行列数和操作数
		int r0=r,c0=c;
		//记录初始的行和列
		for(int i=1;i<=r;i++)
		{
			for(int j=1;j<=c;j++)
			{
				d[i][j]=i*BIG+j;
				//先将电子表的每一个单元格初始化
			}
		}
		while(n--)
		{
			scanf("%s",cmd);
			//读入命令
			if(cmd[0]=='E')
			{//交换单元格命令
				scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
				int t=d[r1][c1];
				d[r1][c1]=d[r2][c2];
				d[r2][c2]=t;
			}
			else
			{//如果是插入/删除命令
				int a,x;
				scanf("%d",&a);
				//a用于存储要插入/删除的行/列的个数
				memset(cols,0,sizeof(cols));
				//创建一个全为零的行/列
				for(int i=0;i<a;i++)
				{//用于读入要执行插入/删除操作的行/列
					scanf("%d",&x);
					//读入行/列
					cols[x]=1;
					//将该行/列设置为1
				}
				if(cmd[0]=='D') del(cmd[1]);
				//如果是删除操作
				else ins(cmd[1]);
				//如果是插入操作
			}
		}
		memset(ans,0,sizeof(ans));
		//将最终结果的电子表格全部初始化为0
		for(int i=1;i<=r;i++)
		{
			for(int j=1;j<=c;j++)
			{
				ans[d[i][j]/BIG][d[i][j]%BIG]=i*BIG+j;
			}
		}
		if(kase>0) printf("\n");
		printf("Spreadsheet #%d\n",++kase);
		scanf("%d",&q);
		//读入要查询的个数
		while(q--)
		{
			scanf("%d%d",&r1,&c1);
			//读入要查询的行列数
			printf("Cell data in (%d,%d) ",r1,c1);
			if(ans[r1][c1]==0) printf("GONE\n");
			//if the contents of the original cell location were destroyed
			else printf("moved to (%d,%d)\n",ans[r1][c1]/BIG,ans[r1][c1]%BIG);
			//打印查询单元格改变后的位置
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/AlexKing007/p/12339468.html