追踪电子表格中的单元格(Spreadsheet Tracking ACM/ICPC World Finals1997,UVa512)

解决本题最直接的思路是:先模拟增删交换操作,算出最后电子表格的状态,然后执行每次查询.这种方法不仅效率低而且不容易理解

另一种思路,直接追踪要查询的单元格,不用关心整个单元格的变化.

详细注释完整代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <assert.h>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;

#define maxd 10000

struct Command{
	char c[5];//用于输入指令 
	int  r1,c1,r2,c2;//用于交换位置的点 
	int  a,x[20];//用于输入增删行列和个数 
}cmd[maxd];
 
int r,c,n;//电子单元的行列数,和指令数 

int simulate(int* r0,int* c0)
{
    for(int i=0;i<n;i++){
	if(cmd[i].c[0]=='E'){//交换位置,有两个(r1,c1),(r2,c2) 
		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;//记录有效的增删个数 
		for(int j=0;j<cmd[i].a;j++){
		int x=cmd[i].x[j];//记录要进行操作的某一行或列 
		if(cmd[i].c[0]=='I'){//增 
			if(cmd[i].c[1]=='R'&&x<=*r0) dr++;//增加的那一行在所要查找的那一行的前面(或等于) ,那么有效也即++ 
			if(cmd[i].c[1]=='C'&&x<=*c0) dc++;//增加的那一列在所要查找的那一列的前面(或等于) ,那么有效也即++ 
		}
		
		else{//删 
			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 argc, char** argv){//输入控制
	int r0,c0,q,kase=0;
	while(cin>>r>>c>>n&&r){
		for(int i=0;i<n;i++){
		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(kase>0) cout<<endl;
	cout<<"Spreadsheet #"<<++kase<<endl;
	cin>>q;	
	while(q--){
	cin>>r0>>c0;
	cout<<"Cell data in("<<r0<<","<<c0<<")";
	if(!simulate(&r0,&c0)) cout<<"GONE"<<endl;
	else cout<<"move to("<<r0<<","<<c0<<")"<<endl;	
	}
	}
	return 0;
}

附:

//if与else if的区别 
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
	int i,j;
	i=99;
	j=0;
	if(i==99) cout<<"a"<<endl;
	//if(j==0) cout<<"b"<<endl;
	else if(j==0) cout<<"c"<<endl;//if(i==99)正确的话将不执行else下的if
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值