题目描述见:uva 101 or poj 1208
关键在于彻底理解题目中搬积木的几个命令的含义,见具体分析
如果还不能理解题意,那么找一个正确通过的代码,编译并输入测试数据,查看其每一个命令的执行情况。如我的代码中162行注释内容取消后即可显示每一步执行后当前积木的情况)
这个题目似乎没有合适的数据结构,由于插入删除操作较多,所以直接用了链表,并且使用双重指针,差点把自己搞晕。(另外,刚开始写的代码能在poj1208上通过,但不能在uva 101上通过,后来发现是141行中的continue误写成了break。网上也有类似的情况,似乎是因为没有考虑到特殊情况的处理(即两个积木块号相同或者处于同一列时需要忽略该命令))
相关C语言代码:
/* uva 101 or poj 1208 */ /*the Blocks problem */ #include <stdio.h> #include <stdlib.h> #include <string.h>struct node {int data;struct node *prev;struct node *next; }; typedef struct node *pBlock; static void CreateHeader(pBlock *ppBlk) {pBlock newBlk = malloc(sizeof(*newBlk));newBlk -> next = newBlk->prev = NULL;(*ppBlk) = newBlk; } static void InsertOnFirst(pBlock *ppBlk, int data) {pBlock newBlk = malloc(sizeof(*newBlk));newBlk -> data = data;newBlk -> next = NULL;newBlk -> prev = *ppBlk;(*ppBlk)->next = newBlk; } static int FindBlock(pBlock *ppBlk, int blockNumber, pBlock *ppretBlock) {pBlock tmpBlk = (*ppBlk)->next;while(tmpBlk != NULL)if(tmpBlk->data == blockNumber){*ppretBlock = tmpBlk;return 1;}elsetmpBlk = tmpBlk->next;return 0; } static void PopAllFollowBlks(pBlock *ppBTab,pBlock *ppBlk) {pBlock tmpBlk,curBlk = (*ppBlk)->next;(*ppBlk)->next = NULL;while(curBlk != NULL){tmpBlk = curBlk;curBlk = curBlk->next;ppBTab[tmpBlk->data] ->next = tmpBlk;tmpBlk->next = NULL;tmpBlk->prev = ppBTab[tmpBlk->data];} }static void MoveOnto(pBlock *ppBTab,pBlock *ppSrcBlk, pBlock *ppDstBlk) {PopAllFollowBlks(ppBTab,ppSrcBlk);PopAllFollowBlks(ppBTab,ppDstBlk);/*pBlock pSrcTmpBlk = pSrcBlk->next,pDstTmpBlk=pDstBlk->next;*/(*ppSrcBlk)->prev->next = NULL;(*ppSrcBlk) ->next = (*ppDstBlk)->next;(*ppSrcBlk)->prev = (*ppDstBlk);(*ppDstBlk)->next = (*ppSrcBlk); } static void MoveOver(pBlock *ppBTab,pBlock *ppSrcBlk, pBlock *ppDstBlk) {pBlock lastDstBlk = (*ppDstBlk);PopAllFollowBlks(ppBTab,ppSrcBlk);(*ppSrcBlk)->prev->next = NULL;while(lastDstBlk->next != NULL)lastDstBlk = lastDstBlk->next;(*ppSrcBlk)->next = lastDstBlk->next;(*ppSrcBlk)->prev = lastDstBlk;lastDstBlk->next = (*ppSrcBlk); } static void PileOnto(pBlock *ppBTab,pBlock *ppSrcBlk, pBlock *ppDstBlk) {PopAllFollowBlks(ppBTab,ppDstBlk);(*ppSrcBlk)->prev->next = NULL;(*ppDstBlk)->next = *ppSrcBlk;(*ppSrcBlk)->prev = *ppDstBlk; } static void PileOver(pBlock *ppBTab,pBlock *ppSrcBlk, pBlock *ppDstBlk) {pBlock lastDstBlk = (*ppDstBlk);(*ppSrcBlk)->prev->next = NULL;while(lastDstBlk->next != NULL)lastDstBlk = lastDstBlk->next;(*ppSrcBlk)->prev = lastDstBlk;lastDstBlk->next = (*ppSrcBlk); } static void PrintBlock(pBlock pBlk) {pBlock tmpBlk = (pBlk) -> next;while(tmpBlk != NULL){printf(" %d",tmpBlk->data);tmpBlk = tmpBlk -> next;}printf("\n"); } static void PrintBlks(pBlock *ppBlk, int arraysize) {int i;for(i = 0; i < arraysize; i++){printf("%d:",i);PrintBlock(ppBlk[i]);} }int main(void) {int n;pBlock *ppBlks,pSrcBlk,pDstBlk;char str1[10],str2[10];int fstBlkNum,scdBlkNum,i,j;int isFound1, isFound2;scanf("%d",&n);getchar();ppBlks = malloc(n * sizeof(*ppBlks));for(i = 0; i < n; i++){CreateHeader(&ppBlks[i]);InsertOnFirst(&ppBlks[i],i);}/* PrintBlks(ppBlks,n);*/while(1){scanf("%s",str1);if(strcmp(str1,"quit") == 0)break;scanf("%d %s %d",&fstBlkNum,str2,&scdBlkNum);if(fstBlkNum == scdBlkNum)continue;for(i = 0; i < n; i++){isFound1 = FindBlock(&ppBlks[i],fstBlkNum,&pSrcBlk);if(isFound1)break;}for(j = 0; j < n; j++){isFound2 = FindBlock(&ppBlks[j],scdBlkNum,&pDstBlk);if(isFound2)break;}if(i != j && strcmp(str1,"move") == 0 && strcmp(str2,"onto") == 0)MoveOnto(ppBlks,&pSrcBlk,&pDstBlk);else if(i != j && strcmp(str1,"move") == 0 && strcmp(str2,"over") == 0)MoveOver(ppBlks,&pSrcBlk,&pDstBlk);else if(i != j && strcmp(str1,"pile") == 0 && strcmp(str2,"onto") == 0)PileOnto(ppBlks,&pSrcBlk,&pDstBlk);else if(i != j && strcmp(str1,"pile") == 0 && strcmp(str2,"over") == 0)PileOver(ppBlks,&pSrcBlk,&pDstBlk);/* PrintBlks(ppBlks,n);*/}PrintBlks(ppBlks,n); return 0; }
另外一种方案(使用栈进行操作):
#include <stdio.h> #include <stdlib.h> #include <string.h>#define MINSTACKSIZE 30 #define STACKINCREMENT 30 struct stack{int capacity;int top;int *array; }; typedef struct stack Stack;Stack *CreateStack() {Stack *pStk = malloc(sizeof(*pStk));pStk->array = malloc(MINSTACKSIZE*sizeof(*(pStk->array)));if(pStk->array == NULL){fprintf(stderr,"error:no space to allocate.\n");exit(EXIT_FAILURE);}else{pStk->capacity = MINSTACKSIZE;pStk->top = 0;}return pStk; }int IsStackEmpty(Stack *pStk) {return pStk->top == 0; } int IsStackFull(Stack *pStk) {return pStk->capacity == pStk->top + 1; } int Push(Stack *pStk, int data) {if(IsStackFull(pStk)){pStk->array = realloc(pStk, (pStk->capacity+STACKINCREMENT)*sizeof(*(pStk->array)));if(pStk->array == NULL){fprintf(stderr, "error: no space to allocate\n");exit(EXIT_FAILURE);}else{pStk -> capacity += STACKINCREMENT;}}pStk -> array[++(pStk -> top)] = data;return 0; } int Pop(Stack *pStk) {if(IsStackEmpty(pStk)){fprintf(stderr,"error: empty stack can pop nothing\n");exit(EXIT_FAILURE);}elsereturn pStk->array[(pStk -> top) --] ; } int Top(Stack *pStk) {if(IsStackEmpty(pStk)){fprintf(stderr,"error: empty stack don't have top element\n");exit(EXIT_FAILURE);}elsereturn pStk->array[pStk -> top] ; }int Find(Stack *pStk, int data) {int i;for(i = 1; i <= pStk->top; i++)if(pStk -> array[i] == data)break;if(i > pStk->top)return 0;elsereturn i; }int PopFollowingBack(Stack **ppStkArray, int index, int pos) {Stack *pCurStk = ppStkArray[index];int curData;while(pCurStk -> top > pos){curData = Pop(pCurStk);/* pTmpStk = ppStkArray[curData];*/Push(ppStkArray[curData],curData);}return 0; } int PushCurAndFollowing(Stack **ppStkArray, int srcIndex, int srcPos, int dstIndex, int dstPos) {int i,srcTop = ppStkArray[srcIndex] -> top;for(i = srcPos; i <= srcTop; i++){Push(ppStkArray[dstIndex],ppStkArray[srcIndex]->array[i]);}ppStkArray[srcIndex] -> top -= srcTop - srcPos + 1;return 0; } int MoveOnto(Stack **ppStkArray,int srcIndex,int srcPos,int dstIndex,int dstPos) {PopFollowingBack(ppStkArray,srcIndex,srcPos);PopFollowingBack(ppStkArray,dstIndex,dstPos);PushCurAndFollowing(ppStkArray,srcIndex,srcPos,dstIndex,dstPos);return 0; } int MoveOver(Stack **ppStkArray,int srcIndex,int srcPos,int dstIndex,int dstPos) {PopFollowingBack(ppStkArray,srcIndex,srcPos);PushCurAndFollowing(ppStkArray,srcIndex,srcPos,dstIndex,dstPos);return 0; } int PileOnto(Stack **ppStkArray,int srcIndex,int srcPos,int dstIndex, int dstPos) {PopFollowingBack(ppStkArray,dstIndex,dstPos);PushCurAndFollowing(ppStkArray,srcIndex,srcPos,dstIndex,dstPos);return 0; } int PileOver(Stack **ppStkArray,int srcIndex,int srcPos,int dstIndex,int dstPos) {PushCurAndFollowing(ppStkArray,srcIndex,srcPos,dstIndex,dstPos);return 0; }void PrintStack(Stack *pStk) {int i;for(i = 1; i <= pStk->top; i++)printf(" %d",pStk->array[i]);printf("\n"); } void PrintAllBlocks(Stack **ppStk, int blockNum) {int i;for(i = 0; i < blockNum; i++){printf("%d:",i);PrintStack(ppStk[i]);} } int main(void) {Stack **ppStkArray;int n;int i,j;char str1[10],str2[10];int srcData,dstData;int srcPos,dstPos;scanf("%d",&n);ppStkArray = malloc(n*sizeof(*ppStkArray));for(i = 0; i < n; i++){ ppStkArray[i] = CreateStack();Push(ppStkArray[i],i);}/* PrintAllBlocks(ppStkArray,n);printf("after popping %d\n",Pop(ppStkArray[2]));PrintAllBlocks(ppStkArray,n);*/while(1){scanf("%s",str1);if(strcmp(str1,"quit")==0)break;scanf("%d %s %d",&srcData,str2,&dstData);if(srcData == dstData)continue;for(i = 0; i < n; i++){srcPos = Find(ppStkArray[i],srcData);if(srcPos)break;}for(j = 0; j < n; j++){dstPos = Find(ppStkArray[j],dstData);if(dstPos)break;}if(i == j)continue;else{if(strcmp(str1,"move") == 0 && strcmp(str2, "onto") == 0)MoveOnto(ppStkArray,i,srcPos,j,dstPos);else if(strcmp(str1,"move") == 0 && strcmp(str2, "over") == 0)MoveOver(ppStkArray,i,srcPos,j,dstPos);else if(strcmp(str1,"pile") == 0 && strcmp(str2, "onto") == 0)PileOnto(ppStkArray,i,srcPos,j,dstPos);else if(strcmp(str1,"pile") == 0 && strcmp(str2, "over") == 0)PileOver(ppStkArray,i,srcPos,j,dstPos);/*PrintAllBlocks(ppStkArray,n);*/}}PrintAllBlocks(ppStkArray,n);return 0; }