例题4-5 追踪电子表格中的单元格 UVa512

来源:互联网 发布:66是什么意思网络用语6 编辑:程序博客网 时间:2024/05/17 02:38

算法竞赛入门经典(第2版)第4章 函数和递归

例题4-5 追踪电子表格中的单元格  UVa512

感悟。

1、阅读书中题目,从网站下载英文原题,重点在看输出数据与格式,叙述过程太繁琐,没耐心看下去。

2、立马打开Excel模拟了一遍,看懂题意了。

3、理解如下:数据输入输出流程,先定row,col;数据操作:增删改;数据查询,查询输出,完整的一轮表格处理结束。

3、写代码时,先把功能框架搭起来,一个功能一个功能的写,同时也一个功能一个功能的输出,大大提高了代码的成功率,同时也代码跨度时间也有两天。

4、冒泡排序,插入排序的类似算法用了许多,可见基础的重要。

5、写好代码,156行,觉得有些冗余,到达一定水平后,应能控制在80行以内,测试数据通过,提交Wrong answer

6、准备翻看书本,估计还是输入输出的理解上有差异。

7、直接看书中代码主函数main部分,结合原题,发现Separate output from different spreadsheets with a blank line.没考虑到,修改,提交Wrong answer.

8、翻看http://blog.csdn.net/thudaliangrx/article/details/50700688也是WA,重回书本,看看该怎么改。

9、像一个好学生一样,不停对照书中代码的输出与本人代码的输出,一模一样,怎么会一直WA。

10、偶然一试越界的情况,差异马上就出来了,本人代码的鲁棒性(健壮性)不够,对付越界删除插入有问题。

如图

书中代码数据输入输出,如下图:

本人代码数据输入输出,如下图:

大家看出差别了吗。

11、开始增强鲁棒性(健壮性), 提交WA,傻了。

12、有没有可能是没有初始化,引起的错误,马上加上memset(cell,0,sizeof(cell));提交WA。

13、刷新了两个小时,才看到结果,AC,此刻已是2016年8月16日10点16分,激动人心的一刻,等得太久了。

14、怎么AC啦,各位看官请听我慢慢道来。

15、经历了12条,已经准备放弃了,但还是不甘心啊,按照书本思路,改进了核心代码处理部分,但输入输出部分还是保持原来的编码,提交WA。

16、那只能是输入输出部分出问题,书本程序,自个编写程序在程序运行后,对比了输入输出,完全一样啊。

17、直接对照书本程序,自个编写程序输入输出部分的源代码,不经意间看到一句,

马上改成:

提交AC,多出的%,看输出结果是看不到的,只有查源代码,这个错误怎么纠正,没办法,只有读源代码,太难啦。

18、开始改最开始的程序,看看提交的结果,需要考虑11条吗?提交WA。看来要考虑鲁棒性(健壮性)。

19、提交11条鲁棒性(健壮性)对应的代码,提交WA。

20、AC代码为参考书中思想编写。

21、采用同种功能进行替换的办法,将提交AC中的功能用有问题的代码中的功能进行一一替换,提交,发现有问题代码中的插入行,插入列,交换数据,输出数据功能AC,删除行,删除列,WA,这样就把精力集中在这两个功能上,待会,好好研读代码,看是否能将这两个功能AC。又发现了一个排错的好办法,在没有足够的输入输出测试数据情况下。

22、经过排查,发现本人代码只适合先删除后插入,若是先插入后删除,则输出数据错误。

修改前局部代码:


修改后局部代码:


23、至此按自个思想编写的程序终于AC了。

24、验证11条健壮性,发现不考虑,提交就WA。

25、附上AC代码,基本上是自个思想的代码。

26、查看UVa网站记录,一共提交28次,至此此题宣告攻克,时间2016年8月17日21:29。

附上代码

环境Dev-cpp4.9.9.2

#include <stdio.h>
#include <string.h>

struct node{
    int r;
    int c;
};
struct node cell[100][100];
void printcell(int r,int c){//打印cell数据,测试用
    int i,j;
    for(i=1;i<=r;i++){
        for(j=1;j<=c;j++){
            printf("%d,%d ",cell[i][j].r,cell[i][j].c);
        }
        printf("\n");
    }
}

int main(){
    int r,c,n,i,A,j,k,l,t,r1,c1,r2,c2,kase,m;
    char cmd[20];
    int a[20];
    struct node tmpcell;
    kase=0;
    while(scanf("%d%d",&r,&c)==2&&r&&c){
        memset(cell,0,sizeof(cell));//结构体也可以memset,初始化为0
        for(i=1;i<=r;i++)//根据行列初始化表格
            for(j=1;j<=c;j++){
                cell[i][j].r=i;
                cell[i][j].c=j;
            }
        scanf("%d",&n);//增删改
        for(i=0;i<n;i++){
            scanf("%s",cmd);
            if(strcmp(cmd,"DR")==0){//删除行
                scanf("%d",&A);
                memset(a,0,sizeof(a));
                k=0;
                for(j=0;j<A;j++){
                    scanf("%d",&t);
                    if(t>=1&&t<=r)//健壮性,保证删除行在表格数据范围内
                        a[k++]=t;
                }
                A=k;
                for(j=0;j<A;j++)//将要删除行,标记数据为0
                    for(k=1;k<=c;k++){
                        cell[a[j]][k].r=0;
                        cell[a[j]][k].c=0;
                    }
                for(j=0;j<A;j++)//自小到大排序
                    for(k=j+1;k<A;k++){
                        if(a[j]>a[k]){
                            t=a[j];
                            a[j]=a[k];
                            a[k]=t;
                        }
                    }
                for(l=0;l<A;l++)//类似冒泡排序
                    for(j=1;j<=r;j++){
                        if(j==a[l]){//整行的处理。
                            for(m=j;m<=r-1;m++)
                                for(k=1;k<=c;k++){
                                    tmpcell=cell[m][k];
                                    cell[m][k]=cell[m+1][k];
                                    cell[m+1][k]=tmpcell;
                                }
                            for(k=0;k<A;k++)//删除一行后,a[]数组中的值整体-1
                                a[k]--;
                        }
                            
                    }
                
                r-=A;//将总行数更新
            }else if(strcmp(cmd,"DC")==0){//删除列
                scanf("%d",&A);
                memset(a,0,sizeof(a));
                k=0;
                for(j=0;j<A;j++){
                    scanf("%d",&t);
                    if(t>=1&&t<=c)
                        a[k++]=t;
                }
                A=k;
                for(j=0;j<A;j++)
                    for(k=1;k<=c;k++){
                        cell[k][a[j]].r=0;
                        cell[k][a[j]].c=0;
                    }
                for(j=0;j<A;j++)
                    for(k=j+1;k<A;k++){
                        if(a[j]>a[k]){
                            t=a[j];
                            a[j]=a[k];
                            a[k]=t;
                        }
                    }
                for(l=0;l<A;l++)//类似冒泡排序
                    for(j=1;j<=c;j++){
                        if(j==a[l]){//整行的处理。
                            for(m=j;m<=c-1;m++)
                                for(k=1;k<=r;k++){
                                    tmpcell=cell[k][m];
                                    cell[k][m]=cell[k][m+1];
                                    cell[k][m+1]=tmpcell;
                                }
                            for(k=0;k<A;k++)//删除一列后,a[]数组中的值整体-1
                                a[k]--;
                        }
                            
                    }
                
                c-=A;//将总行数更新
            }else if(strcmp(cmd,"IR")==0){//插入行
                scanf("%d",&A);
                memset(a,0,sizeof(a));
                for(j=0;j<A;j++){
                    scanf("%d",&a[j]);
                }
                for(j=0;j<A;j++){//冒泡排序,自小到大
                    for(k=j+1;k<A;k++){
                        if(a[j]>a[k]){
                            t=a[j];
                            a[j]=a[k];
                            a[k]=t;
                        }
                    }
                }
                for(j=0;j<A;j++)//查询是否越界
                    if(a[j]>r)
                        break;
                if(j<A)//越界处理,A值变小
                    A=j;
                for(l=0;l<A;l++){
                    for(j=r;j>=a[l]+l;j--){//插入行
                        for(k=1;k<=c;k++){
                            cell[j+1][k].r=cell[j][k].r;
                            cell[j+1][k].c=cell[j][k].c;
                        }
                    }
                    for(k=1;k<=c;k++){
                        cell[a[l]+l][k].r=0;
                        cell[a[l]+l][k].c=0;
                    }
                    r+=1;
                }
            }else if(strcmp(cmd,"IC")==0){//插入列
                scanf("%d",&A);
                memset(a,0,sizeof(a));
                for(j=0;j<A;j++){
                    scanf("%d",&a[j]);
                }
                for(j=0;j<A;j++){//冒泡排序,自小到大
                    for(k=j+1;k<A;k++){
                        if(a[j]>a[k]){
                            t=a[j];
                            a[j]=a[k];
                            a[k]=t;
                        }
                    }
                }
                for(j=0;j<A;j++)//查询是否越界
                    if(a[j]>c)
                        break;
                if(j<A)//越界处理,A值变小
                    A=j;
                for(l=0;l<A;l++){
                    for(j=c;j>=a[l]+l;j--){//插入列
                        for(k=1;k<=r;k++){
                            cell[k][j+1].r=cell[k][j].r;
                            cell[k][j+1].c=cell[k][j].c;
                        }
                    }
                    for(k=1;k<=r;k++){
                        cell[k][a[l]+l].r=0;
                        cell[k][a[l]+l].c=0;
                    }
                    c+=1;
                }
            }else if(strcmp(cmd,"EX")==0){
                scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
                tmpcell=cell[r1][c1];
                cell[r1][c1]=cell[r2][c2];
                cell[r2][c2]=tmpcell;
            }
        }
        kase++;
        if(kase>1)
            printf("\n");
        printf("Spreadsheet #%d\n",kase);
        scanf("%d",&n);//查
        for(i=0;i<n;i++){
            scanf("%d%d",&r1,&c1);
            printf("Cell data in (%d,%d) ",r1,c1);
            for(j=1;j<=r;j++){
                for(k=1;k<=c;k++){
                    if(cell[j][k].r==r1&&cell[j][k].c==c1){
                        printf("moved to (%d,%d)\n",j,k);
                        break;
                    }
                }
                if(k<=c)//查询到,退出
                    break;
            }
            if(j==r+1)//未查询到
                printf("GONE\n");
        }
    }
    return 0;
}


0 0
原创粉丝点击