uva 512 - Spreadsheet Tracking(Excel表格)

例题4-5 踪电子表格中的单元格(Spreadsheet Tracking, ACM/ICPC World Finals
1997, UVa512)
有一个r行c列(1≤r,c≤50)的电子表格,行从上到下编号为1~r,列从左到右编号为1
~c。如图4-2(a)所示,如果先删除第1、5行,然后删除第3, 6, 7, 9列,结果如图4-2(b)
所示。
(a) (b)
图4-2 删除行、列
接下来在第2、3、5行前各插入一个空行,然后在第3列前插入一个空列,会得到如图4-
3所示结果。
图4-3 插入行、列
你的任务是模拟这样的n个操作。具体来说一共有5种操作:
EX r1 c1 r2 c2交换单元格(r1,c1),(r2,c2)。
A x1 x2 … xA 插入或删除A行或列(DC-删除列,DR-删除行,IC-插入
列,IR-插入行,1≤A≤10)。
在插入/删除指令后,各个x值不同,且顺序任意。接下来是q个查询,每个查询格式
为“r c”,表示查询原始表格的单元格(r,c)。对于每个查询,输出操作执行完后该单元格的新
位置。输入保证在任意时刻行列数均不超过50。
Sample Input
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
Sample Output
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)

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=832&problem=453&mosmsg=Submission+received+with+ID+20782890

注意:
输入注意以 0 0 结束,输出每两次输出间以一行空行隔开,最后一次输出后不能有空行

移动前
这里写图片描述
移动后
这里写图片描述

这道题很繁琐,最后一直过不了参考了例题的代码,简单说一下思路。
-1、我们先定义两个二维数组,一个用于操作(我们称其为 原始数组),另一个用于将操作完的数据拷贝过来(我们将其称为 临时数组),再将整理好的数据考回第一个数组,用于下次操作
0、而且我们的每个元素的数值也是有蹊跷的,最好是要看着元素的值就能知道它起初的位置。我们可以用,
① 第 i 行 第 j 列元素 =(i - 1)* 总列数 + j - 1;之所以要减一是因为我的数组计数是从下标0开始,其实这样不太好,容易混乱,像书上一样从1开始就不错
②书上是这个意思:先定义一个大数BIG=10000;第 i 行 第 j 列元素 = i * BIG +j ;这样的话 行数就是在万位以上了,和列数分开了。我们只要用 元素 / BIG 和 元素 % BIG 就能得到 行和列的序号。
1、删除:先记录要删除的行(列)序号,再在原始数组中将这一行(列)的数据变成0,然后在复制给临时数组时,判断不是0的拷贝即可
2、复制:这个方法是采用了书上的,之后我再说我的不好的方法。
我们事先定义一个一维数组,用这个数组记录下要加的行(列),要加的行(列)序号就在 对应的一维数组的下标的元素记为1,然后在拷贝时,我们依次判断一维数组的各个元素是不是1,是则停止原始数组的拷贝,加入一行(列)元素都为0的行,否则拷贝一行(列)原始数组
3、交换:直接交换
4、判断坐标:
①我一开始的方法是先通过原始坐标 算出那个位置上的原始元素值,然后依次遍历更改后的数组,找到了就输出当前所遍历到的行和列的序号,没找到就是GONE了
②书上的意思是:又创建了一个二维数组用此数组记录改变的情况:
ans[此元素的][原始位置] = 代表“改变后的位置”的数值
所以我们分析一个原始位置,就可以直接通过下标来找到改变后的位置。
这两种方法各有好坏,前者费时节省空间,后者费空间省时;不过你也可以不用创建新的数组,用临时数组来记录应该也行。这样的话就不比前者方法费空间了

#include<iostream>
#include<string>
#include<iomanip>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAX = 100;

int oper_list[MAX][MAX],temp_list[MAX][MAX],ans_list[MAX][MAX];
int cols[MAX];
int rnum,cnum;//行数,列数
void Roper_to_temp(int T=0)
{
    memset(temp_list,0,sizeof(temp_list));
    int in=0;//记录增加到第几个了
    int temp_r=0;
    for(int i=0;i<rnum;i++)
    {
        //cout<<i<<" =?= "<<rnum+in<<"  "<<oper_list[rnum+in][0]<<endl;
        if(T&&cols[i]==1)
        {
            for(int j=0;j<cnum;j++)
                temp_list[temp_r][j]=0;
            temp_r++;
        }
//        if(T&&in<T&&i+1==oper_list[rnum+in][0])//若当前行是要增加的行
//        {
//            in++;
//            //cout<<in<<"  !! "<<temp_r<<endl;
//            for(int j=0;j<cnum;j++)
//                temp_list[temp_r][j] = 0;
//            temp_r++;
//            i--;
//            continue;
//        }
        if(oper_list[i][0]==-1)//代表这一行要删掉
            continue;
        for(int j=0;j<cnum;j++)
            temp_list[temp_r][j] = oper_list[i][j];
        temp_r++;
    }
}
//void Roper_to_temp(int T=0)
//{
//    int n=0;
//    for(int i=0;i<rnum+T;i++)
//    {
//        if(i==temp_list[rnum+n][0])
//        {
//            n++;
//  `         i++;
//            continue;
//        }
//        for(int j=0;j<cnum;j++)
//            temp_list[i][j] = oper_list[i][j];
//    }
//}
void Coper_to_temp(int T=0)
{
    memset(temp_list,0,sizeof(temp_list));
    int in=0;
    int temp_c=0;
    //cout<<"ttt "<<T<<endl;
    for(int i=0;i<cnum;i++)//注意 +T
    {
//        cout<<"copy temp "<<temp_c<<endl;
//        cout<<"in "<<in<<"  operlist  "<<oper_list[0][cnum+in]<<endl;
        if(T&&cols[i]==1)
        {
            for(int j=0;j<rnum;j++)
                temp_list[j][temp_c]=0;
            temp_c++;
        }
//        if(T&&in<T&&i+1==oper_list[0][cnum+in])//若当前列是要增加的行
//        {
//            in++;
//            for(int j=0;j<rnum;j++)
//                temp_list[j][temp_c] = 0;
//            temp_c++;
//            i--;
//            continue;
//        }
        if(oper_list[0][i]==-1)//代表这一列要删掉
            continue;
        for(int j=0;j<rnum;j++)
            temp_list[j][temp_c] = oper_list[j][i];
        temp_c++;
    }
}
void temp_to_oper()
{
    memcpy(oper_list,temp_list,sizeof(temp_list));
//    for(int i=0;i<rnum;i++)
//        for(int j=0;j<cnum;j++)
//            oper_list[i][j] = temp_list[i][j];
}
void dr_oper()
{
    int T;
    cin>>T;//增加的次数
    int oper;//oper[15];
    for(int i=0;i<T;i++)
    {
        cin>>oper;//[i];
        for(int j=0;j<cnum;j++)//删除的行中的值变成 -1
            oper_list[oper-1][j]= -1;
    }
    Roper_to_temp();
    rnum-=T;//行数少T
    temp_to_oper();

}
void dc_oper()
{
    int T;
    cin>>T;
    int oper;
    for(int i=0;i<T;i++)
    {
        cin>>oper;
        for(int j=0;j<rnum;j++)//删除的列中值变成 -1
            oper_list[j][oper-1]=-1;
    }

    Coper_to_temp();
    cnum-=T;//列数少T
    temp_to_oper();

}

void ir_oper()
{
    memset(cols,0,sizeof(cols));
    int T;
    cin>>T;
    int oper;
    for(int i=0;i<T;i++)
    {
        cin>>oper;
        cols[oper-1]=1;
        //oper_list[rnum+i][0]=oper;//最后加一行,第一个元素值是要加的行号
    }


    Roper_to_temp(T);
    rnum+=T;//行数多T
    temp_to_oper();
}
void ic_oper()
{
    memset(cols,0,sizeof(cols));
    int T;
    cin>>T;
    int oper;
    for(int i=0;i<T;i++)
    {
        cin>>oper;
        cols[oper-1]=1;
        //oper_list[0][cnum+i]=oper;
        //cout<<"oper  "<<cnum+i<<" "<<oper_list[0][cnum+i]<<endl;
    }

    Coper_to_temp(T);
    cnum+=T;//列数多T
    temp_to_oper();




}
void exc_oper()
{
    int r1,c1,r2,c2;
    cin>>r1>>c1>>r2>>c2;
    int temp = oper_list[r1-1][c1-1];
    oper_list[r1-1][c1-1] = oper_list[r2-1][c2-1];
    oper_list[r2-1][c2-1] = temp;
}
void visit(int Cn)//遍历的方法
{
    int x,y;
    int iff=0;
    cin>>x>>y;
    //cout<<"!!"<<(x-1)*Rn+y<<endl;
    for(int i=0;i<rnum;i++)
        for(int j=0;j<cnum;j++)
        {
            if(oper_list[i][j]==(x-1)*Cn+y)
            {
                iff=1;
                printf("Cell data in (%d,%d) moved to (%d,%d)\n",x,y,i+1,j+1);
                return;
            }
        }
    if(iff==0)
    {
        printf("Cell data in (%d,%d) GONE\n",x,y);
    }

}


const int BIG = 10000;
void visit2()//数组按址索迹
{
    int x,y;
    cin>>x>>y;
    printf("Cell data in (%d,%d) ",x,y);
    if(ans_list[x][y]==0)
        cout<<"GONE"<<endl;
    else
        printf("moved to (%d,%d)\n",ans_list[x][y]/BIG,ans_list[x][y]%BIG);
}
int main()
{
    int T=1;
    while(cin>>rnum>>cnum&&rnum!=0&&cnum!=0)
    {

        memset(oper_list,0,sizeof(oper_list));
//        if(rnum==0&&cnum==0)
//            break;

        int Cn=cnum;//用于遍历时留存的列数
        for(int i=0;i<rnum;i++)
            for(int j=0;j<cnum;j++)
                oper_list[i][j]=(i+1)*BIG+j+1;//i*cnum+j+1;//从1开始依次给值

//        for(int i=0;i<rnum;i++)
//        {
//            for(int j=0;j<cnum;j++)
//                cout<<setw(3)<<oper_list[i][j];
//            cout<<endl;
//        }

        int T_DI;//操作数
        cin>>T_DI;
        while(T_DI--)
        {
            string DIRC;//char DIRC[4];
            //int DI_num;
            cin>>DIRC;
            if(DIRC=="DR")
                dr_oper();
            else if(DIRC=="DC")
                dc_oper();
            else if(DIRC=="IR")
                ir_oper();
            else if(DIRC=="IC")
                ic_oper();
            else if(DIRC=="EX")
                exc_oper();

//        cout<<endl<<rnum<<" * "<<cnum<<endl;
//        for(int i=0;i<rnum;i++)
//        {
//            for(int j=0;j<cnum;j++)
//                cout<<setw(3)<<oper_list[i][j];
//            cout<<endl;
//        }
        }

        memset(ans_list,0,sizeof(ans_list));
        for(int i=1;i<=rnum;i++)//打表,记录元素先后位置
            for(int j=1;j<=cnum;j++)
                ans_list[oper_list[i-1][j-1]/BIG][oper_list[i-1][j-1]%BIG]=(i)*BIG+j;
                //ans[此元素的][原始位置] = 代表’改变后的位置‘的 数值
        if(T>1)
            cout<<endl;
        cout<<"Spreadsheet #"<<T++<<endl;
        int T_xy;
        cin>>T_xy;
        while(T_xy--)
            visit2();
            //visit(Cn);//认祖归宗
    }
    return 0;
}
//AC at 2018/2/16

这篇文章就这吧,太累了,这道题遇到几个坎:1、不理解题,2、提交不过
一旦理解题目,思路不难,写,然后通过样例改代码。
最后就连udebug上面的100个案例都过了,还是通过不能,想死。后来采用忒休斯船法,将书上的代码一部分一部分换,看换成什么样的时候能通过,最后换了增加行列的函数时通过,喜极而嚎。
udebug上的样例最大直到行列20,还是小。
www.udebug.com还是太棒了,不写了不写了,感冒头晕不想看见代码,时间不早还有英语要背

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值