1. 程式人生 > >uva 509 Raid技術 紫書4-7

uva 509 Raid技術 紫書4-7

uva 509 Raid技術 紫書4-7

今天呀,本來是想去參加廣工的新生網賽,1點到5點,特意準備的。但結果不知道杭電的oj參賽要提前報名,呃,進不去,只用過csu的oj,那好吧,就做紫書上的題吧。

初代程式完成了。大致思路是把輸入的資料用二維陣列儲存起來,然後判斷,如果有的行沒有出現x,則效驗結果應該正確,否則輸出 磁碟非法,跳出迴圈。如果有一個x,則可以恢復,那就通過異或恢復x,如果兩個x或以上,那無法恢復,輸出磁碟非法跳出迴圈。
恢復後,按照四個位元的二進位制轉換為10進位制並依此輸出16進位制結果。

第一次除錯,發現自己的二維數組裡的資料是getchar得來的,計算時應該減去’0’轉換為原本的數字。

第二次除錯,發現自己忽略了題目條件 如果資料不滿4個位元則在後面加0。

第三次除錯,發現自己雖然寫了奇校驗和偶校驗變數,實際上有一種情況沒有分類討論,故出錯了。

三次除錯後通過樣例輸入,下面提交oa。
第一次wa,使用debug板塊,看看哪裡出錯了.
debug板塊給的兩個樣例,全過了,真不知道為什麼wa。

經過自己仔細思考,發現犯了和象棋那題一樣的錯誤。我的判斷是如果到了最後一組,位元數還不足四位那就直接輸出。可是有一種情況,最後一組如果是效驗碼呢?那效驗碼就被跳過了,最後還是會有一個數因為沒滿4位元而沒有輸出。於是我又加了個判斷,如果這是倒數第二組數,而最後一組數是效驗碼,那麼直接輸出,無論滿了四位沒。

然後就ac啦。
大致思路就是儲存,然後判斷加復原。
復原後怎麼輸出結果呢?
每達到四個位元就輸出一個十六進位制,最後一組未達到則直接輸出。由於題目要求16進位制大寫,所以要用%X來輸出。
設disk1 disk2 disk3 這個是行,那disk1的內容就是列
用一個三重迴圈,第一層是列的遞增,第二層是行的遞增,第三層也是列,但是隻要遞增到了s個位元就結束第三層迴圈,換個磁碟繼續加。
大致意思就是每個磁碟的一格有s個位元,s個位元加完了就加下一個磁碟。而這一行的磁碟的位元都加完了,就跳轉到下一列,也就是磁碟的第二格,繼續加,依此迴圈,每四位的二進位制轉換為10進位制,並以%X輸出。

然後怎麼保證不輸出校驗碼呢?加一個變數代表當前列數。該變數對磁碟個數取餘數,得到的就是效驗碼所在的磁碟行數,加個if判斷,如果該行不等於餘數,才進行迴圈的計算。

下面放程式碼,沒寫註釋,思路已經寫在上面了。

#include<stdio.h>
#include<string.h>
#include<math.h>
int data[7][6500],d,s,b,kase=0,eo1,dd[6500],jj[6500];
int main()
{
    freopen("input.txt","r",stdin);
    while0:
    while(scanf("%d%d%d",&d,&s,&b)==3&&d)
    {   memset(data,0,sizeof(data));
        memset(dd,0,sizeof(dd));
        memset(jj,0,sizeof(jj));
        char eo[2];
        scanf("%s",&eo);
        if(eo[0]=='E') eo1=0;
        else if(eo[0]=='O') eo1=1;
        getchar();
        int sb=s*b;
        for(int i=0;i<d;i++)
        {
            for(int j=0;j<sb;j++)
            {
                data[i][j]=getchar();
            }
            getchar();
        }
            for(int j=0;j<sb;j++)
            {
                for(int i=0;i<d;i++)
                {
                    if (data[i][j]=='x'){dd[j]++;jj[j]=i;}
                }
            }
        for (int j=0;j<sb;j++)
        {
            int c=eo1;
            if (dd[j]==0)
            {

                for (int i=0;i<d;i++)
                {
                    c=c^(data[i][j]-'0');
                }
                if (c!=0){printf("Disk set %d is invalid.\n",++kase);goto while0;}
            }
            else if(dd[j]==1)
            {
                for(int i=0;i<jj[j];i++)
                {
                    c=c^(data[i][j]-'0');
                }
                for(int i=jj[j]+1;i<d;i++)
                {
                    c=c^(data[i][j]-'0');
                }
                int unknow=jj[j];
                data[unknow][j]=(c+'0');
            }
            else if(dd[j]>1){printf("Disk set %d is invalid.\n",++kase);goto while0;}
        }
        int count2=3,number=0;
        printf("Disk set %d is valid, contents are: ",++kase);
        int booll=0;
        for (int j=0;j<sb;j=j+s)
        {
            for(int i=0;i<d;i++)
            {
                if(i!=booll%d){
                for (int j1=j;j1<j+s;j1++)
                {
                    number+=((data[i][j1]-'0')*pow(2,count2));
                    count2--;
                    if(j1==sb-1&&i==d-1){count2=-1;}
                    if(j1==sb-1&&i==d-2&&(i+1)==booll%d){count2=-1;}
                    if(count2==-1){printf("%X",number);number=0;count2=3;}
                }
                }
            }
            booll++;
        }
        printf("\n");
    }
    return 0;
}

加油哦!!!