题解 UVA512 【追踪电子表格中的单元格 Spreadsheet Tracking】

WanderingTrader

2020-10-16 22:47:25

Solution

思路和汝佳老师的一致,即保存所有操作,每次对单个单元格执行所有操作,不过写法上稍有不同(毕竟没人会用C风格的指针来做吧)。 ### 题目分析 我们定义一个结构体 Command 来保存每一条命令: ```cpp struct Command { string cmd; int n,a[11]; }; ``` 其中 cmd 表示命令的种类,如果cmd为`EX`,那么四个数分别保存在a[1...4]中。否则用n表示条数,a[1...n]表示数据。 那么基本框架如下: ```cpp using namespace std; const int maxn=1e5+5; int n,q; struct Command { string cmd; int n,a[11]; }; Command cmds[maxn]; int main() { int r,c,kase=0; while(~scanf("%d%d",&r,&c)&&r) { if(kase) printf("\n"); printf("Spreadsheet #%d\n",++kase); scanf("%d",&n); for(int i=1;i<=n;++i) { cin>>cmds[i].cmd; if(cmds[i].cmd=="EX") { scanf("%d",&cmds[i].a[1]); scanf("%d",&cmds[i].a[2]); scanf("%d",&cmds[i].a[3]); scanf("%d",&cmds[i].a[4]); } else { scanf("%d",&cmds[i].n); for(int j=1;j<=cmds[i].n;++j) scanf("%d",&cmds[i].a[j]); } } scanf("%d",&q); while(q--) { int a,b; scanf("%d%d",&a,&b); solve(a,b); } } return 0; } ``` 重点就在于solve函数的实现。 首先我们观察输出中的重复部分:`Cell data in (,)`,所以我们先将其输出,可以减少代码量: ```cpp void solve(int x,int y) { printf("Cell data in (%d,%d) ",x,y); } ``` 接下来遍历每一条语句,如果是`EX`,而且交换的单元格中有当前的x,y,那么执行交换: ```cpp for(int i=1;i<=n;++i) { int cntx=0,cnty=0; if(cmds[i].cmd=="EX") { if(cmds[i].a[1]==x&&cmds[i].a[2]==y) { x=cmds[i].a[3]; y=cmds[i].a[4]; } else if(cmds[i].a[3]==x&&cmds[i].a[4]==y) { x=cmds[i].a[1]; y=cmds[i].a[2]; } } } ``` 否则就遍历该命令中的每一个目标行/列,分情况操作。 注意操作是打包在一起的,所以对x和y的移动要先记录下来,执行完该条命令以后一起操作。 ```cpp else for(int j=1;j<=cmds[i].n;++j) ``` 如果命令为`DR`,那么若被删除的行号u=x,则直接输出`GONE`并退出,若u<x,那么x对应的行会往上一个,x减一: ```cpp if(cmds[i].cmd=="DR") { if(cmds[i].a[j]==x) { printf("GONE\n"); return; } else if(cmds[i].a[j]<x) --cntx; } ``` `DC`与`DR`几乎完全一样,只是把x换成了y而已: ```cpp else if(cmds[i].cmd=="DC") { if(cmds[i].a[j]==y) { printf("GONE\n"); return; } else if(cmds[i].a[j]<y) --cnty; } ``` 如果是`IR`,那么如果被添加的行u<=x(注意u=x的时候也是),就把x加一,`IC`同理: ```cpp else if(cmds[i].cmd=="IR") { if(cmds[i].a[j]<=x) ++cntx; } else if(cmds[i].a[j]<=y) ++cnty; ``` 执行完一整条语句后把x,y做对应的修改即可: ```cpp x+=cntx;y+=cnty; ``` 最后打印出移动后的位置: ```cpp printf("moved to (%d,%d)\n",x,y); ``` solve函数完整代码如下: ```cpp void solve(int x,int y) { printf("Cell data in (%d,%d) ",x,y); for(int i=1;i<=n;++i) { int cntx=0,cnty=0; if(cmds[i].cmd=="EX") { if(cmds[i].a[1]==x&&cmds[i].a[2]==y) { x=cmds[i].a[3]; y=cmds[i].a[4]; } else if(cmds[i].a[3]==x&&cmds[i].a[4]==y) { x=cmds[i].a[1]; y=cmds[i].a[2]; } } else for(int j=1;j<=cmds[i].n;++j) { if(cmds[i].cmd=="DR") { if(cmds[i].a[j]==x) { printf("GONE\n"); return; } else if(cmds[i].a[j]<x) --cntx; } else if(cmds[i].cmd=="DC") { if(cmds[i].a[j]==y) { printf("GONE\n"); return; } else if(cmds[i].a[j]<y) --cnty; } else if(cmds[i].cmd=="IR") { if(cmds[i].a[j]<=x) ++cntx; } else if(cmds[i].a[j]<=y) ++cnty; } x+=cntx;y+=cnty; } printf("moved to (%d,%d)\n",x,y); } ``` 注意,本题的输出需要在 **第二组及以后的表格之前输出一个空行**。 模拟题考的还是耐心,要能静下心来调错。 $$\texttt{The End.}$$