关键在于彻底理解题目中搬积木的几个命令的含义,见具体分析
如果还不能理解题意,那么找一个正确通过的代码,编译并输入测试数据,查看其每一个命令的执行情况。如我的代码中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;
}
else
tmpBlk = 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);
}
else
return 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);
}
else
return 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;
else
return 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;
}

本文详细介绍了如何使用C语言解决积木搬运问题,包括理解题目中的指令、选择合适的链表数据结构、处理特殊情况进行代码优化。文章提供了两种解决方案,一种是使用链表操作,另一种是使用栈进行操作,并在代码实现中遇到并解决了错误。
3131

被折叠的 条评论
为什么被折叠?



