题意:
模拟表格的操作:插入行、列,删除行、列,交换格子
题目要求对给出的格子坐标,输出一系列操作后的格子坐标或 GONE。
思路:
我们的思路是记录下操作,然后对每一个坐标进行一遍操作。
先来讲记录操作,我直接用 int 数组记录的,可以将操作进行编号,将编号记录在每一行的 0 下标位置处,如 EX 为 1, DC 为 2, DR 为 3, IC 为 4, IR 为 5,int 数组为 cmd[100010][20](题目中说了 A 不会超过 10,所以列数选 20 足够),cmd[][0] 位置就用来记录操作的编号。至于操作后的数字,可以直接记录到 cmd[][0] 的后面。
然后讲对每一个坐标进行操作,
从题目中我们能够看到如果原先的坐标是 (x, y),
如果是插入行,在 x 前面(包括 x)插入了几行 x 就要加上几;
如果是插入列,在 y 前面(包括 y)插入了几列 y 就要加上几;
如果是删除行,如果删除的行里有 x,则这个坐标就 GONE 了,否则在 x 前面(不包括 x)删除了几行 x 就要减去几;
如果是删除列,如果删除的列里有 y,则这个坐标就 GONE 了,否则在 y 前面(不包括 y)删除了几行 y 就要减去几;
如果是交换格子,比如 (x1, y1) 和 (x2, y2) 互换,如果 (x1, y1) 就是 (x, y),那么 (x, y) 的坐标交换后就变成了 (x2, y2),如果 (x2, y2) 就是 (x, y),那么 (x, y) 的坐标交换后就变成了 (x1, y1)。
这里我们只要按着上面的逻辑和我们储存的操作格式去编写代码就可以了。
下面对样例进行解析:
按照 EX 为 1, DC 为 2, DR 为 3, IC 为 4, IR 为 5 记录下操作后的数组为
坐标 (4, 8) 执行完第一个操作后变成 (3, 8),
执行完第二个操作后变成 (3, 5),
执行完第三个操作后变成 (3, 6),
执行完第四个操作后变成 (4, 6),
执行完第五个操作后变成 (4, 6),
所以结果是 Cell data in (4,8) moved to (4,6)
坐标 (5, 5) 执行完第一个操作后就 GONE 了,
所以结果是 Cell data in (5,5) GONE
坐标 (7, 8) 执行完第一个操作后变成 (5, 8),
执行完第二个操作后变成 (5, 5),
执行完第三个操作后变成 (5, 6),
执行完第四个操作后变成 (7, 6),
执行完第五个操作后变成 (7, 6),
所以结果是 Cell data in (7,8) moved to (7,6)
坐标 (6, 5) 执行完第一个操作后变成 (4, 5),
执行完第二个操作后变成 (4, 4),
执行完第三个操作后变成 (4, 5),
执行完第四个操作后变成 (6, 5),
执行完第五个操作后变成 (1, 2),
所以结果是 Cell data in (6,5) moved to (1,2)
注意:
1. 输出的时候字母别打错了,,,我就在这 WA 了一次
2. 题目中有这样一句话 For each insert and delete
command, the order of the rows or columns in the command has no signicance. 意思就是删除和插入的时候,所以删除或插入的行或列的序号顺序没有意义。即我们删除和插入时要拿原始的坐标和所删除或插入行或列的号比较,而不是删除一个行改变一次坐标再去删除下一行。在一次删除或插入的操作里,只能在最后出现一次对坐标的加减。
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<stack>
#include<queue>
#include<utility>
#include<vector>
#include<cmath>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
#include<sstream>
using namespace std;
typedef long long LL;
int r, c;
int n, m;
int cmd[100010][20]; //EX = 1, DC = 2, DR = 3, IC = 4, IR = 5
int main()
{
freopen("in.txt", "r", stdin);
int kase = 1;
while(scanf("%d%d", &r, &c)==2 && r!=0 && c!=0){
scanf("%d", &n);
char ch[5];
for(int i=0; i<n; i++){
scanf("%s", ch);
if(strcmp(ch, "EX") == 0){
cmd[i][0] = 1;
for(int j=1; j<=4; j++){
scanf("%d", &cmd[i][j]);
}
}else{
if(strcmp(ch, "DC") == 0) cmd[i][0] = 2;
else if(strcmp(ch, "DR") == 0) cmd[i][0] = 3;
else if(strcmp(ch, "IC") == 0) cmd[i][0] = 4;
else if(strcmp(ch, "IR") == 0) cmd[i][0] = 5;
scanf("%d", &cmd[i][1]);
for(int j=2; j<2+cmd[i][1]; j++){
scanf("%d", &cmd[i][j]);
}
}
}
if(kase != 1) printf("\n");
printf("Spreadsheet #%d\n", kase++);
scanf("%d", &m);
int r1, c1;
for(int i=0; i<m; i++){
scanf("%d%d", &r1, &c1);
printf("Cell data in (%d,%d) ", r1, c1);
for(int j=0; j<n; j++){
if(cmd[j][0] == 1){ //EX,交换
if(cmd[j][1]==r1 && cmd[j][2]==c1){
r1 = cmd[j][3]; c1 = cmd[j][4];
}else if(cmd[j][3]==r1 && cmd[j][4]==c1){
r1 = cmd[j][1]; c1 = cmd[j][2];
}
}else if(cmd[j][0] == 2){ //DC,删除列
int tmp = 0;
for(int k=2; k<2+cmd[j][1]; k++){
if(cmd[j][k] == c1){
c1 = -1; break;
}else if(cmd[j][k] < c1){
tmp++;
}
}
if(c1 != -1) c1 -= tmp;
}else if(cmd[j][0] == 3){ //DR,删除行
int tmp = 0;
for(int k=2; k<2+cmd[j][1]; k++){
if(cmd[j][k] == r1){
r1 = -1; break;
}else if(cmd[j][k] < r1){
tmp++;
}
}
if(r1 != -1) r1 -= tmp;
}else if(cmd[j][0] == 4){ //IC,插入列
int tmp = 0;
for(int k=2; k<2+cmd[j][1]; k++){
if(cmd[j][k] <= c1){
tmp++;
}
}
c1 += tmp;
}else if(cmd[j][0] == 5){ //IR,插入行
int tmp = 0;
for(int k=2; k<2+cmd[j][1]; k++){
if(cmd[j][k] <= r1){
tmp++;
}
}
r1 += tmp;
}
printf("%d, %d\n", r1, c1);
if(r1<0 || c1<0) break;
}
if(r1<0 || c1<0){
printf("GONE\n");
}else{
printf("moved to (%d,%d)\n", r1, c1);
}
}
}
return 0;
}
想看书上的源代码的话看这 (^▽^)
https://github.com/aoapc-book/aoapc-bac2nd