UVa 127 "Accordian" Patience

~~~题目链接~~~


题目大意:现在有52张牌, 从牌顶开始发牌,发的牌从左到右一张一张的铺好, 当发的当前这张牌与左边第一张或左边第三张牌花色或点数相同时,发的这张牌移动到左边第一张或左边第三张上面(这时成了一个堆), 如果这张牌移动过后又与左边第一张或第三张花色或点数相同就在继续移动。当有多张牌可以移动时, 先移动左边的。当一张牌即可以移动到左边第三张和第一张上时, 移动到左边第三张上。求发完52张牌后,最后剩下有多少堆牌, 和每堆的数量。(从左到右输出)


思路:建立一个堆,用链表链接起来, 递归的进行模拟。具体解释看代码(注: 带有头结点的链表)

Ps:描述中左右与题中的相反


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct stack
{
    char c[5];
};
typedef struct node
{
    char c[5]; //栈顶元素
    struct stack s[56];//每叠的堆
    int top;
    struct node *next;
}*list;
int judge1(list l)
{
    return (l->next != NULL && l->next->next != NULL && l->next->next->next != NULL && l->next->next->next->next != NULL);
}
int judge2(list l)
{
    return (l->next != NULL && l->next->next != NULL);
}


void f(list l)
{
    int top1 = 0, top2 = 0;
    list p;
   // if(l == NULL) return ;
    if(l->next == NULL) return ;
    if(l->next->next == NULL ) return ;//不能向右移
    else if(judge1(l))//可以向右移动3位
    {
        top1 = l->next->top;
        while(top1 != 0 && judge1(l) &&( l->next->next->next->next->c[0] == l->next->c[0] || l->next->next->next->next->c[1] == l->next->c[1] ))
        {//向右移3位
            top2 = l->next->next->next->next->top;
            strcpy(l->next->next->next->next->s[top2++].c, l->next->c);//入栈
            strcpy(l->next->next->next->next->c, l->next->c);//设置顶端元素
            l->next->next->next->next->top++;//栈加1
            top1--;
            l->next->top--;
            if(top1)
                strcpy(l->next->c, l->next->s[top1-1].c);
            if(!top1)//如果为空向右移,合并
            {
                p = l->next;
                l->next = l->next->next;
                top1 = l->next->top;//合并后又可以往右移
                free(p);
            }//注意要先判断是否合并了,及时合并
            f(l->next->next->next);//进行后继的判断,右边的牌先判断,递归进行
            f(l->next->next);
            f(l->next);
        }
    }
    if(judge2(l))//与右边一位对比
    {
        top1 = l->next->top;
        while(top1 != 0 && judge2(l) && (l->next->next->c[0] == l->next->c[0] || l->next->next->c[1] == l->next->c[1]))
        {
            top2 = l->next->next->top;
            strcpy(l->next->next->s[top2++].c, l->next->c);
            strcpy(l->next->next->c, l->next->c);
            l->next->next->top++;
            top1--;
            l->next->top--;
            if(top1)
                strcpy(l->next->c, l->next->s[top1-1].c);
            else
            {
                p = l->next;
                l->next = l->next->next;
                free(p);
            }
            f(l->next);
            f(l);//可以往右边移动三个的判断,开始漏掉了这种请况,狂wa,一定要注意当右边有合并时,这时要重新判断右边第三个
        }
    }
}

int main()
{
    int i = 0, j = 0 ,len = 0, top = 0, cnt = 0, ans[60];
    char str1[200], str2[200];
    list l = (list)malloc(sizeof(struct node)), p;
    l->next = NULL;
    while(gets(str1))
    {
        l->next = NULL;
        cnt = 0;
        if(str1[0] == '#') break;
        len = strlen(str1);
        str1[len] = ' ';
        gets(str1+len+1);
        len = strlen(str1);
        for(i = 0; i<len; i += 3)
        {
            p = (list)malloc(sizeof(struct node));
            p->c[0] = str1[i];
            p->c[1] = str1[i+1];
            p->c[3] = '\0';
            strcpy(p->s[0].c, p->c);
            p->top = 1;
            p->next = l->next;
            l->next = p;
            f(l);
        }
        for(p = l->next; p; p = p->next)
        {
            top = p->top;
            ans[cnt++] = top;
        }
        if(cnt == 1)
            printf("%d pile remaining:", cnt);
        else
            printf("%d piles remaining:", cnt);
        for(i = cnt-1; i>-1; i--)
            printf(" %d", ans[i]);
        printf("\n");
    }
    return 0;
}


你可能感兴趣的:(UVa 127 "Accordian" Patience)