UVA - 512 Spreadsheet Tracking

Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu

 Status

Description

Download as PDF

Data in spreadsheets are stored in cells, which are organized in rows (r) and columns (c). Some operations on spreadsheets can be applied to single cells (r,c), while others can be applied to entire rows or columns. 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. The spreadsheet then shrinks to the one on the right.


$\textstyle \parbox{.5\textwidth}{\begin{center}\begin{tabular}{r\vert r\vert ......4 & 35 & 36 & 22 & 38 & 39 & 40 & 41\\ \cline{2-10}\end{tabular}\end{center}}$$\textstyle \parbox{.49\textwidth}{\begin{center}\begin{tabular}{r\vert r\vert......4 & 35 & 36 & 22 & 38 & 39 & 40 & 41\\ \cline{2-10}\end{tabular}\end{center}}$

If the user subsequently marks columns 3, 6, 7, and 9 for deletion, the spreadsheet shrinks to this.


$\searrow$12345
122482216
21819212225
32425672271
41612102258
53334362240

If the user marks rows 2, 3 and 5 for insertion, the spreadsheet grows to the one on the left. If the user then marks column 3 for insertion, the spreadsheet grows to the one in the middle. Finally, if the user exchanges the contents of cell (1,2) and cell (6,5), the spreadsheet looks like the one on the right.


$\textstyle \parbox{.33\textwidth}{\begin{center}\begin{tabular}{r\vert r\vert......cline{2-6}8 & 33 & 34 & 36 & 22 & 40\\ \cline{2-6}\end{tabular}\end{center}}$$\textstyle \parbox{.33\textwidth}{\begin{center}\begin{tabular}{r\vert r\vert......ine{2-7}8 & 33 & 34 & & 36 & 22 & 40\\ \cline{2-7}\end{tabular}\end{center}}$$\textstyle \parbox{.32\textwidth}{\begin{center}\begin{tabular}{r\vert r\vert......ine{2-7}8 & 33 & 34 & & 36 & 22 & 40\\ \cline{2-7}\end{tabular}\end{center}}$

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 (   r) and columns (   c), followed by an integer specifying the number (   n) of spreadsheet operations. Row and column labeling begins with 1. The maximum number of rows or columns of each spreadsheet is limited to 50. The following n lines specify the desired operations.


An operation to exchange the contents of cell (r1c1) with the contents of cell (r2c2) is given by:


EXr1c1r2c2


The four insert and delete commands--DC (delete columns), DR (delete rows), IC (insert columns), and IR (insert rows) are given by:


<commandAx1x2$\dots$xA


where <command> is one of the four commands; A is a positive integer less than 10, and $x_1, \dots, x_A$ are the labels of the columns or rows to be deleted or inserted before. 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 andc, representing the row and column number of a cell in the original spreadsheet. For each query, your program must determine the current location of the data that was originally in cell (rc). 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). 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. 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.

Sample Input 

7 9
5
DR   2  1 5
DC  4  3 6 7 9
IC  1  3
IR  2  2 4
EX 1 2 6 5
4
4 8
5 5
7 8
6 5
0 0

Sample Output 

Spreadsheet #1
Cell data in (4,8) moved to (4,6)
Cell data in (5,5) GONE
Cell data in (7,8) moved to (7,6)
Cell data in (6,5) moved to (1,2)

方法之一是模拟操作,得出操作后的表格,在用一个表格记录原表格的各个位置。
代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int BIG = 10000;
const int MAXN = 100;

int r, c, n, d[MAXN][MAXN], d2[MAXN][MAXN], cols[MAXN],ans[MAXN][MAXN];   
//d存改变后的数组,数组元素为原来的位置。d2辅助数组,ans数组为原来的数组,元素为改变后的位置。cols数组用来记录每次操作的行或列。

void copy(char type, int p, int q)           //copy函数完成把q行(或列)复制到p行(或列)。
{
	if (type == 'R')
	{
		for (int i = 1; i <= c; i++)
			d[p][i] = d2[q][i];
	}
	else
	{
		for (int i = 1; i <= r; i++)
			d[i][p] = d2[i][q];
	}
}

void del(char type)              //删除
{
	memcpy(d2, d, sizeof(d));
	int cnt = (type == 'R' ? r : c);
	int cnt2 = 0;
	for (int i = 1; i <= cnt; i++)          //即把没有删除的复制到一个表中
	{
		if (!cols[i])
			copy(type, ++cnt2, i);
	}
	if (type == 'R') r = cnt2; else c = cnt2;   //更新行数和列数
}

void ins(char type)
{
	memcpy(d2, d, sizeof(d));
	int cnt = (type == 'R' ? r: c);
	int cnt2 = 0;
	for (int i = 1; i <= cnt; i++)            //插入全0行(列)到i行(列)前
	{
		if (cols[i]) copy(type, ++cnt2, 0);
			copy(type, ++cnt2, i);
	}
	if (type == 'R') r = cnt2; else c = cnt2;
}

int main()
{
	char op[10];
	int r1, c1, r2, c2, a, x ,casen=0;
	int q, rr, cc;
	while (cin >> r >> c)
	{
		if (r == 0) break;
		
		cin >> n;
		for (int i = 1; i <= r;i++)
		for (int j = 1; j <= c; j++)
			d[i][j] = i*BIG + j;            //通过BIG的辅助存单元格原位置
		
		while (n--)
		{
			cin >> op;
			if (op[0] == 'E')             //交换单元格
			{
				cin >> r1 >> c1 >> r2 >> c2;
				int t = d[r1][c1];
				d[r1][c1] = d[r2][c2];
				d[r2][c2] = t;
			}
			else
			{
				memset(cols, 0, sizeof(cols));   //一定要初始化
				cin >> a;
				for (int i = 0; i < a; i++)
				{
					cin >> x;
					cols[x] = 1;                 //记录要改变的行或列
				}
				if (op[0] == 'D') del(op[1]);  
				else ins(op[1]);
			}
		}

		memset(ans, 0, sizeof(ans));
		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;         //ans数组记录原表格中各个单元格的新位置

		if (casen > 0) cout << endl;
		cout << "Spreadsheet #" << ++casen << endl;

		cin >> q;
		while (q--)
		{
			cin >> rr >> cc;
			printf("Cell data in (%d,%d) ", rr, cc);              //用printf较不会出现pe
			if (ans[rr][cc] == 0) printf("GONE\n");
			else
				printf("moved to (%d,%d)\n", ans[rr][cc] / BIG, ans[rr][cc] % BIG);
		}
	}
	return 0;
}

另一个方法是将所有的操作保存,然后对每个查询重新执行每个操作,但不需要计算整个电子表格的变化,而只需要关注所查询的单元格的位置变化。对于题目给定的规模来看,这个方法不仅更好写,而且效率更高。
代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAXN = 10000;

struct Command        //用cmd数组保存所有操作。
{
	char c[5];
	int r1, c1, r2, c2;
	int a, x[20];
}cmd[MAXN];                    
int r, c, n;

int simulate(int* r0, int* c0)         //对所查询单元格模拟操作,返回操作后的位置(如果单元格被删去返回0)
{
	for (int i = 0; i < n; i++)
	{
		if (cmd[i].c[0] == 'E')        //交换后到另一格
		{
			if (cmd[i].r1 == *r0 && cmd[i].c1 == *c0) { *r0 = cmd[i].r2; *c0 = cmd[i].c2; }
			else if (cmd[i].r2 == *r0 && cmd[i].c2 == *c0) { *r0 = cmd[i].r1; *c0 = cmd[i].c1; }
		}
		else
		{
			int dr = 0, dc = 0;             //dr,dc记录行或列的增减
			for (int j = 0; j < cmd[i].a; j++)
			{
				int x = cmd[i].x[j];
				if (cmd[i].c[0] == 'I')             //插入列(或列),只有插入在r0(c0)前的才会对其有影响。
				{
					if (cmd[i].c[1] == 'R' && x <= *r0) dr++;
					if (cmd[i].c[1] == 'C' && x <= *c0) dc++;
				}
				else                                //删除行(列),直接删去r0(c0)或删去其前面的有影响。
				{
					if (cmd[i].c[1] == 'R' && x == *r0) return 0;
					if (cmd[i].c[1] == 'C' && x == *c0) return 0;
					if (cmd[i].c[1] == 'R' && x < *r0) dr--;
					if (cmd[i].c[1] == 'C' && x < *c0) dc--;
				}
			}
			*r0 += dr; *c0 += dc;           //更新单元格的新位置
		}
	}
	return 1;
}

int main()
{
	int r0, c0, q, casen = 0;
	while (cin >> r >> c)
	{
	if (r == 0) break;
		cin >> n;
		for (int i = 0; i < n; i++)               //输入操作,分EX和其他两种输入。
		{
			cin >> cmd[i].c;
			if (cmd[i].c[0] == 'E') cin >> cmd[i].r1 >> cmd[i].c1 >> cmd[i].r2 >> cmd[i].c2;
			else {
				cin >> cmd[i].a;
				for (int j = 0; j < cmd[i].a; j++)
					cin >> cmd[i].x[j];
			}
		}
		
		if (casen > 0) cout << endl;                   //注意格式
		cout << "Spreadsheet #" << ++casen << endl;
		
		scanf("%d", &q);
		while (q--)
		{
			scanf("%d%d", &r0, &c0);
			printf("Cell data in (%d,%d) ", r0, c0);
			if (!simulate(&r0, &c0)) printf("GONE\n");
			else printf("moved to (%d,%d)\n", r0, c0);
		}
	}
	return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这波lucio来全学了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值