思路一:首先进行模拟操作,算出最后的整个电子表格,然后每次查询时直接在电子表格中找到所求的单元格。
d[i][j]表示变化后的电子表格中坐标为i,j的单元格所存储的原来表格中的单元格坐标信息。
ans[i][j]表示原来坐标为i,j的单元格现在的位置。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxh 50000
using namespace std;
int i,j,r,c,r1,c1,r2,c2,orr,orc,tim,t1,options,num,testnum,target;
char op[3];int d[51][51];int d2[51][51];int mark[51];int ans[51][51];
void copyi(char s,int p,int q);
void exchange(int r1,int c1,int r2,int c2);
void del(char s);
void ins(char s);
int main()
{
tim=1;
while((cin>>r>>c)&&r)
{
if(tim>1)
{
cout<<endl;
}
cout<<"Spreadsheet #"<<tim<<endl;tim++;
memset(d,0,sizeof(d));
memset(d2,0,sizeof(d2));
for(i=1;i<=r;i++)
for(j=1;j<=c;j++)
{
d[i][j]=i*maxh+j;
}
cin>>options;
while(options--)
{
cin>>op;
if(op[0]=='E')
{
cin>>r1>>c1>>r2>>c2;
exchange(r1,c1,r2,c2);
}
else if(op[0]=='D')
{
cin>>num;
memset(mark,0,sizeof(mark));
while(num--)
{
cin>>target;
mark[target]=1;
}
del(op[1]);
}
else if(op[0]=='I')
{
cin>>num;
memset(mark,0,sizeof(mark));
while(num--)
{
cin>>target;
mark[target]=1;
}
ins(op[1]);
}
}
memset(ans,0,sizeof(ans));
for(i=1;i<=r;i++)
for(j=1;j<=c;j++)
{
ans[d[i][j]/maxh][d[i][j]%maxh]=i*maxh+j;
}
cin>>testnum;
while(testnum--)
{
cin>>orr>>orc;
cout<<"Cell data in ("<<orr<<","<<orc<<") ";
if(ans[orr][orc]==0)
{
cout<<"GONE"<<endl;
}
else
{
cout<<"moved to ("<<(ans[orr][orc]/maxh)<<","<<(ans[orr][orc]%maxh)<<")"<<endl;
}
}
}
}
void copyi(char s,int p,int q)
{
if(s=='R')
{
for(int k=1;k<=c;k++)
{
d[p][k]=d2[q][k];
}
}
else
{
for(int k=1;k<=r;k++)
{
d[k][p]=d2[k][q];
}
}
}
void exchange(int r1,int c1,int r2,int c2)
{
t1=d[r1][c1];
d[r1][c1]=d[r2][c2];
d[r2][c2]=t1;
}
void del(char s)
{
memcpy(d2,d,sizeof(d));
int cnt=s=='R'?r:c,cnt2=0;
for(i=1;i<=cnt;i++)
{
if(!mark[i])
{
copyi(s,++cnt2,i);
}
}
if(s=='R')
{
r=cnt2;
}
else
{
c=cnt2;
}
}
void ins(char s)
{
memcpy(d2,d,sizeof(d));
int cnt=s=='R'?r:c,cnt2=0;
for(int i=1;i<=cnt;i++)
{
if(mark[i])
{
copyi(s,++cnt2,0);
}
copyi(s,++cnt2,i);
}
if(s=='R')
{
r=cnt2;
}
else
{
c=cnt2;
}
}
思路二:将所有的操作保存,然后对于每一个查询重新执行每个操作,不需要计算整个电子表格的变化,只需要关注所查询的单元格的位置变化。此方法更为简便,效率高。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxh 50000
using namespace std;
int r,c,orr,orc,tim,options,testnum;
struct Command{
char ch[5];
int r1,c1,r2,c2;
int a,x[20];
}cmd[maxh];
int simulate();
int main()
{
tim=1;
while((cin>>r>>c)&&r)
{
if(tim>1)
{
cout<<endl;
}
cout<<"Spreadsheet #"<<tim<<endl;tim++;
cin>>options;
for(int i=0;i<options;i++)
{
cin>>cmd[i].ch;
if(cmd[i].ch[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];
}
}
}
cin>>testnum;
while(testnum--)
{
cin>>orr>>orc;
cout<<"Cell data in ("<<orr<<","<<orc<<") ";
if(!simulate())
{
cout<<"GONE"<<endl;
}
else
{
cout<<"moved to ("<<orr<<","<<orc<<")"<<endl;
}
}
}
}
int simulate()
{
for(int i=0;i<options;i++)//每一条指令执行后,需要更新坐标值
{
if(cmd[i].ch[0]=='E')
{
if(cmd[i].r1==orr&&cmd[i].c1==orc)
{
orr=cmd[i].r2;orc=cmd[i].c2;
}
else if(cmd[i].r2==orr&&cmd[i].c2==orc)
{
orr=cmd[i].r1;orc=cmd[i].c1;
}
}
else
{
int dr=0,dc=0;//每一条指令 删除/增添若干行/列,行与行,列与列变化是同时进行的,所以需要先保持orr,orc不发生变化,然后操作完成一步后再进行运算
for(int j=0;j<cmd[i].a;j++)
{
int k=cmd[i].x[j];
if(cmd[i].ch[0]=='D')
{
if((cmd[i].ch[1]=='R'&&k==orr)||(cmd[i].ch[1]=='C'&&k==orc))
{
return 0;
}
if(cmd[i].ch[1]=='R'&&k<orr)
{
dr--;
}
if(cmd[i].ch[1]=='C'&&k<orc)
{
dc--;
}
}
else//插入空行
{
if(cmd[i].ch[1]=='R'&&k<=orr)
{
dr++;
}
if(cmd[i].ch[1]=='C'&&k<=orc)
{
dc++;
}
}
}
orr+=dr;orc+=dc;
}
}
return 1;
}