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;
}
加油哦!!!