程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> UVa 127 "Accordian" Patience

UVa 127 "Accordian" Patience

編輯:C++入門知識

題目大意:現在有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; 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved