uva 196 Spreadsheet

在poj上也有 是poj 1420,在poj上AC了,但是在UVA上RE

题意:很好理解就是给你一个表格,一些元素已经有数字了,一些元素还不知道,但是它等于某些元素相加的和,要你补完整个表格

(行用1到999表示,列用大写字母来表示,用ABC开始一直到ZZZ,这个很容易算出来,26+26*26+26*26*26=18278,字符处理有些麻烦,代码中的funtion函数)

这个东西一开始没想到是什么,后来喵了一下解题报告说是拓扑排序,瞬间就懂了,因为有些元素是未知的,未知的元素是由已知的元素相加得到的,那么就是有一个优先关系,看sample就看得出来

然后数据较大,打了一半不知道要怎么做了,然后又轻轻喵了一下解题报告,说是数据没有这么大,开个1001*1001的数组就可以了,然后就这么做,后面的都没看解题报告了

在拓扑排序建图的时候是同邻接表,然后是用链表来实现的,添加元素的时候用了头插法。建好图记录号入度出度之后,然后就是拓扑排序的常规实现了

注释都在代码中,直接看代码,还要再改改代码才能在UVA中AC啊………………

 

在POJ上AC的

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <queue>

using namespace std;

#define N 1010    //行1-999

int n,m;

struct node

{ 

    int x,y;

    struct node *next;

};

struct SHEET

{

    int in,out;

    int v;

    struct node *first;  //邻接表

}sheet[N][N*100];  //据说开到这么大就可以了,18278是吓人的



struct QUEUE

{ int x,y; };

queue <struct QUEUE> q;



void init()

{

    for(int i=1; i<=n; i++)

        for(int j=1; j<=m; j++)

        {

            sheet[i][j].in=sheet[i][j].out=sheet[i][j].v=0;

            sheet[i][j].first=NULL;

        }

    return ;

}

void funtion(char *s , int i , int j)

{

    int len,llen,k,tt,r,c;

    struct node *p;

    char t[100];

    len=strlen(s);

    k=1;

    while(k<len)

    {

        tt=0;

        while(s[k]>='A' && s[k]<='Z')

            t[tt++]=s[k++];

        t[tt]='\0';

        llen=strlen(t);

        if(llen==1)

            c=t[0]-'A'+1;

        else if(llen==2)

            c=26 + (t[1]-'A'+1) + (t[0]-'A'+1-1)*26;

        else    //英文字母长度是3

            c=26+26*26+ (t[2]-'A'+1) + (t[1]-'A'+1-1)*26 + (t[0]-'A'+1-1)*26*26;

        sscanf(s+k,"%d",&r);

        while(s[k]>='1' && s[k]<='9') 

            k++;

        k++;

        //printf("行%d   列%d\n",r,c);



        sheet[i][j].in++;  //没分解出一个元素就要令入度+1

        sheet[r][c].out++;   //出度+1

        p=(struct node*)malloc(sizeof(struct node));

        p->x=i;

        p->y=j;

        p->next=sheet[r][c].first;  //头插法

        sheet[r][c].first=p;        //头插法

    }

}

void input()

{

    int len;

    char s[1100];

    scanf("%d%d",&m,&n);  //先输入列再是行别搞错了

    

    init();  //初始化

    

    for(int i=1; i<=n; i++)

    {

        for(int j=1; j<=m; j++)

        {

            scanf("%s",s);

            if(s[0]=='=')

                funtion(s,i,j);  //字符串处理

            else

                sscanf(s,"%d",&sheet[i][j].v);

        }

    }

/*

    for(int i=1; i<=n; i++)

    {

        for(int j=1; j<=m; j++)

            printf("%d\\%d\\%d  ",sheet[i][j].v,sheet[i][j].out,sheet[i][j].in);

        printf("\n");

    }

    printf("打印邻接表\n");

    for(int i=1; i<=n; i++)

        for(int j=1; j<=m; j++)

            if(sheet[i][j].out)

            {

                struct node *tmp;

                tmp=sheet[i][j].first;

                printf("打印 %d %d 邻接表\n",i,j);

                while(tmp)

                {

                    printf("%d %d\n",tmp->x,tmp->y);

                    tmp=tmp->next;

                }

            }

*/

    return ;

}



void topsort()

{

    struct QUEUE t1,t2;

    struct node t,*p;

    while(!q.empty()) q.pop();

    for(int i=1; i<=n; i++)  

        for(int j=1; j<=n; j++)

        //先扫描所有元素,把所有入度为0的元素放入队列

        //其实就是已经知道了数值不需要计算的元素

        if(!sheet[i][j].in)

        {

            t1.x=i;

            t1.y=j;

            q.push(t1);  //入度

        }

    

    while(!q.empty())

    {

        t1=q.front();  //读取队头元素信息

        q.pop();      //队友元素出队

        int x=t1.x , y=t1.y;

        if(sheet[x][y].out)  

        //在表格中(x , y)这个元素有出度,那么就删除它的所有的弧,弧头的入度也要记得-1

        {

            p=sheet[x][y].first;

            int xx,yy;

            while(p)

            {

                xx=p->x;

                yy=p->y;

                p=p->next;

                sheet[xx][yy].in--;  //对应弧头的入度-1

                sheet[xx][yy].v += sheet[x][y].v; //计算(xx,yy)的值

                if(!sheet[xx][yy].in)  //删除弧之后如果弧头的入度为0则入队

                {

                    t2.x=xx;

                    t2.y=yy;

                    q.push(t2);

                }

            }

            sheet[x][y].first=NULL;

            //这个弧尾的弧已经全部删除了

        }

     }

}

int main()

{

    int T;

    scanf("%d",&T);

    while(T--)

    {

        input();

        topsort();  //开始拓扑排序

        for(int i=1; i<=n; i++)

        {

            int j=1;

            printf("%d",sheet[i][j].v);

            for(j=2; j<=m; j++)

                printf(" %d",sheet[i][j].v);

            printf("\n");

        }

        printf("\n");

    }

    return 0;

}

 

 

在UVA上AC的

(下面是一个很有爱的故事)

今天早上上UVA不知道干嘛超慢,页面半天打不开,然后我在想是不是因为十八大的原因…………(以为又封锁了国外网站什么的)

然后这题在poj过了之后就开始交UVA,一直RE,网上都说数组开到1010*1010就可以了,后来我变为1010*10100之后就不RE了变为WA,然后就检查代码,发现了很多小BUG,例如m写成n,0写成1之类的,所以,在这种情况下POJ都能通过那真的是无语了,然后就改了小BUG,提交一直WA,然后期间又把数组改为1010*1010,又RE,所以就确定了数组使1010*10100,就一直WA,最后去看UVA的讨论版,某个人说过不了,给了几个数据我拿几个数据去测试,是对的,这下子有去面壁。后来发现一个问题,在每个表格输出之后是没有空行的,咦好像是要空行的,然后上网又查代码,发现居然有些人有空行有些人没有!!!!

然后我就消掉空行,提交居然AC了!!!!!就是这个空行啊!!!!!

然后又加了空行再交了几次,确定了,每个表格后面是不用空行的(那些有空行的人是怎么AC的………………)

然后又丢到poj上去,我去!!!!poj有没有空行都能通过的,这是一个多么有爱的故事

这个故事还没有完,要知道我提交是在UVA失常页面老是打不开的情况下提交的,那个心情的

而就在我第一次AC之后………………UVA恢复正常了………………

我的一个晚上又废掉了…………本来今晚要学英语的…………都九点半了…………

献上代码,和poj那个代码是一样的,修改了一些小BUG,不要看POJ那个代码了,直接看这个!

 

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <queue>

using namespace std;

#define N 1010    //行1-999

int n,m;

struct node

{ 

    int x,y;

    struct node *next;

};

struct SHEET

{

    int in,out;

    int v;

    struct node *first;  //邻接表

}sheet[N][N];  //据说开到这么大就可以了,18278是吓人的



struct QUEUE

{ int x,y; };

queue <struct QUEUE> q;



void init()

{

    for(int i=1; i<=n; i++)

        for(int j=1; j<=m; j++)

        {

            sheet[i][j].in=sheet[i][j].out=sheet[i][j].v=0;

            sheet[i][j].first=NULL;

        }

    return ;

}

void funtion(char *s , int i , int j)

{

    int len,llen,k,tt,r,c;

    struct node *p;

    char t[100];

    len=strlen(s);

    k=1;

    while(k<len)

    {

        tt=0;

        while(s[k]>='A' && s[k]<='Z')

        {

            t[tt]=s[k];

            tt++;

            k++;

        }

        t[tt]='\0';

        llen=strlen(t);

        if(llen==1)

            c=t[0]-'A'+1;

        else if(llen==2)

            c=(t[1]-'A'+1) + (t[0]-'A'+1)*26;

        else    //英文字母长度是3

            c=(t[2]-'A'+1) + (t[1]-'A'+1)*26 + (t[0]-'A'+1)*26*26;

        sscanf(s+k,"%d",&r);

        while(s[k]>='0' && s[k]<='9') 

            k++;



        //printf("%s\n",t);

        //printf("行%d   列%d\n",r,c);

        k++;



        sheet[i][j].in++;  //没分解出一个元素就要令入度+1

        sheet[r][c].out++;   //出度+1

        p=(struct node*)malloc(sizeof(struct node));

        p->x=i;

        p->y=j;

        p->next=sheet[r][c].first;  //头插法

        sheet[r][c].first=p;        //头插法

    }



    return ;

}

void input()

{

    int len;

    char s[110000];

    scanf("%d%d",&m,&n);  //先输入列再是行别搞错了

    

    init();  //初始化

    

    for(int i=1; i<=n; i++)

    {

        for(int j=1; j<=m; j++)

        {

            scanf("%s",s);

            if(s[0]=='=')

                funtion(s,i,j);  //字符串处理

            else

                sscanf(s,"%d",&sheet[i][j].v);

        }

    }

/*

    for(int i=1; i<=n; i++)

    {

        for(int j=1; j<=m; j++)

            printf("%d\\%d\\%d  ",sheet[i][j].v,sheet[i][j].out,sheet[i][j].in);

        printf("\n");

    }

    printf("打印邻接表\n");

    for(int i=1; i<=n; i++)

        for(int j=1; j<=m; j++)

            if(sheet[i][j].out)

            {

                struct node *tmp;

                tmp=sheet[i][j].first;

                printf("打印 %d %d 邻接表\n",i,j);

                while(tmp)

                {

                    printf("%d %d\n",tmp->x,tmp->y);

                    tmp=tmp->next;

                }

            }

*/

    return ;

}



void topsort()

{

    int x,y,xx,yy;

    struct QUEUE t1,t2;

    struct node t,*p;

    while(!q.empty()) q.pop();

    for(int i=1; i<=n; i++)  

        for(int j=1; j<=m; j++)

        //先扫描所有元素,把所有入度为0的元素放入队列

        //其实就是已经知道了数值不需要计算的元素

        if(!sheet[i][j].in)

        {

            t1.x=i;

            t1.y=j;

            q.push(t1);  //入度

        }

    

    while(!q.empty())

    {

        t1=q.front();  //读取队头元素信息

        q.pop();      //队友元素出队

        x=t1.x ; y=t1.y;

        if(sheet[x][y].out)  

        //在表格中(x , y)这个元素有出度,那么就删除它的所有的弧,弧头的入度也要记得-1

        {

            p=sheet[x][y].first;

            

            while(p)

            {

                xx=p->x;

                yy=p->y;

                p=p->next;

                sheet[xx][yy].in--;  //对应弧头的入度-1

                sheet[xx][yy].v += sheet[x][y].v; //计算(xx,yy)的值

                if(!sheet[xx][yy].in)  //删除弧之后如果弧头的入度为0则入队

                {

                    t2.x=xx;

                    t2.y=yy;

                    q.push(t2);

                }

            }

            sheet[x][y].first=NULL;

            sheet[x][y].out=0;

            //这个弧尾的弧已经全部删除了

        }

     }

}

int main()

{

    int T;

    scanf("%d",&T);

    while(T--)

    {

        input();

        topsort();  //开始拓扑排序

        for(int i=1; i<=n; i++)

        {

            int j=1;

            printf("%d",sheet[i][j].v);

            for(j=2; j<=m; j++)

                printf(" %d",sheet[i][j].v);

            printf("\n");

        }

        //printf("\n");  

        //我靠…………就是这个东西,WA了3小时………………本来1A的……为什么UVA和POJ这么坑的…………

    }

    return 0;

}

 

 

 

你可能感兴趣的:(Spread)