题意翻译
有一个r行c列(1≤r,c≤50)的电子表格,行从上到下编号为1~r,列从左到右编号为 1~c。如图(a)所示,如果先删除第1、5行,然后删除第3,6,7,9列,结果如图©所示。
接下来在第2、3、5行前各插入一个空行,然后在第3列前插入一个空列, 会得到如图(e)的结果。 你的任务是模拟这样的n个操作。具体来说一共有5种操作
EX r1 c1 r2 c2交换单元格(r1,c1),(r2,c2)
Ax1x2…xA插入或删除A行或列(DC-删除列,DR-删除行,IC插入列,IR-插入行,1≤A≤10)。
在插入删除指令后,各个x值不同,且顺序任意。接下来是q个查询,每个查询格 为“r c”,表示查询原始表格的单元格(r,c)。对于每个查询,输出操作执行完后该单元格 新位置。输入保证在任意时刻行列数均不超过50。
图表从上到下从左到右分别为图(a)-(e)
感谢@BFD_qt 提供翻译
输入输出样例
输入 #1复制
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
输出 #1复制
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)
思路:
两种思路!!!! 一是比较好想的,直接根据操作,按照要求修改表格,最后查询即可。 二是 保存下每次修改操作 ,对于每次询问,重新遍历所有的修改,得出答案。第二种思路更好,效率也更高,但是比较难写。
下面是第一种思路的代码,参考紫书上刘老师的代码,刘老师的巧妙之处在于d2数组的巧妙利用,对于每次修改不是修改,而是重新“做”一张表,“做”的这张表就参考d2数组
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define Maxn 52
#define GI 10000
using namespace std;
int d[Maxn][Maxn],d2[Maxn][Maxn],ans[Maxn][Maxn];
int r,c,n,q,cols[Maxn];
inline void Copy(char typ,int p,int q) {
if(typ == '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];
}
}
inline void Ins(char typ) {
memcpy(d2,d,sizeof(d));
int cnt = typ == 'R' ? r : c,cnt2 = 0;
for(int i=1; i<=cnt; i++) {
if(cols[i]) Copy(typ,++cnt2,0);// 第i行前 插入一行
Copy(typ,++cnt2,i);
}
if(typ == 'R') r = cnt2;
else c = cnt2;
}
inline void Del(char typ) {
memcpy(d2,d,sizeof(d));
int cnt = typ == 'R' ? r : c,cnt2 = 0;
for(int i=1; i<=cnt; i++) {
if(!cols[i]) Copy(typ,++cnt2,i);// 没删除的 复制过来
}
if(typ == 'R') r = cnt2;
else c = cnt2;
}
int main(int argc,char* argv[]) {
int kase = 0,r1,c1,r2,c2,a,x;
char cmd[10];
memset(d,0,sizeof(d));
while(scanf("%d %d %d",&r,&c,&n) == 3 && r) {
for(int i=1; i<=r; i++)
for(int j=1; j<=c; j++)
d[i][j] = i * GI + 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 {
scanf("%d",&a); memset(cols,0,sizeof(cols));
//cols[i]=1电表第i行或者列 需要删除或者增添
for(int i=1; i<=a; i++) { scanf("%d",&x); cols[x] = 1; }
if(cmd[0] == 'D') Del(cmd[1]);
else Ins(cmd[1]);
}
}
memset(ans,0,sizeof(ans));
for(int i=1; i<=r; i++)
for(int j=1; j<=c; j++)
ans[d[i][j] / GI][d[i][j] % GI] = i * GI + j;
if(kase > 0) printf("\n");
printf("Spreadsheet #%d\n", ++kase);
scanf("%d",&a);
while(a--) {
scanf("%d %d",&r1,&c1);
printf("Cell data in (%d,%d) ", r1, c1);
if(ans[r1][c1] == 0) printf("GONE\n");
else printf("moved to (%d,%d)\n", ans[r1][c1] / GI, ans[r1][c1] % GI);
}
}
return 0;
}