首页 > 代码库 > "Accordian" Patience (UVa 127) 双向链表 栈

"Accordian" Patience (UVa 127) 双向链表 栈

题目:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=63

思路:

  从第一个牌堆开始,向右进行遍历。若存在左边第三个牌堆,则优先考虑能否移动到左边第三个牌堆,若不存在或不能移动,再考虑左边第一个牌堆,若都不能移动,则继续考虑下一个牌堆。由于“如果有多张牌可以移动,先移动最左边的牌”,因此进行移动操作以后,要从移动到的那张牌堆开始考虑。每次移动操作都进行牌堆是否为空判断。

 

PS: 不知道为什么,用 cout 输出的话,一提交就 WA,改成 printf 就AC了,活生生卡了2天。

 

代码:

#include <iostream>
#include <stack>
#include <cstdlib>
using namespace std;

const int MAX = 53;

struct Node{
    stack<string> stk;
};

int r[MAX], l[MAX];    //结点的右边、左边 
Node node[MAX];                //牌堆 

void link(int a, int b);    //连接两个结点
void deleteNode(int a);        //删除结点 
void init();                //初始化链表
bool canMove(int a, int b);    //判断能否将 b 的牌顶移到 a 
void move(int a, int b);    //将 b 顶部的牌移到 a 牌堆 
void check(int a);            //如果 a 的牌堆为空,删除
int treblePre(int a);        //a 前面第三个结点,若不存在,返回 0   
bool input();                //输入,若结束返回 false 
void output();                //输出 

int main(){
    
    //freopen("input.txt", "r", stdin);
    
    while(input()){

        int i=r[0];
        while(i != 0){    //一直做到没有后继
            
            int pre1 = treblePre(i);    //前面第三个牌堆 
            int pre2 = l[i];            //前面第一个牌堆 
            
            if(pre1 != 0){        //如果前面第三个牌堆存在 
                if(canMove(pre1, i)){
                    move(pre1, i);        //就进行移动 
                    check(i);            //若为空,删除
                    i = pre1;            //从 pre1 牌堆开始考虑
                    continue; 
                }
            }
            
            if(pre2 != 0){
                if(canMove(pre2, i)){
                    move(pre2, i);        //就进行移动 
                    check(i);            //若为空,删除
                    i = pre2;            //从 pre2 牌堆开始考虑
                    continue; 
                }
            }
            
            i = r[i];                    //如果不能移动,则考虑下一堆 
         
        }
        
        output();        //输出
    }
    
    return 0;
    
}

void link(int a, int b){
    r[a] = b;
    l[b] = a;
} 

void deleteNode(int a){
    link(l[a], r[a]);
} 

void init(){
    for(int i=0; i<MAX-1; i++){            //初始化链 
        link(i, i+1);
    }
    r[52] = 0; 
}

bool canMove(int a, int b){
    
    string s1 = node[a].stk.top();
    string s2 = node[b].stk.top();
    
    if(s1[0] == s2[0] || s1[1] == s2[1]){
        return true;
    }
    
    return false;
    
} 

void move(int a, int b){
    
    node[a].stk.push(node[b].stk.top());
    node[b].stk.pop();
    
} 

void check(int a){
    
    if(node[a].stk.empty()){
        deleteNode(a);
    }
    
}

bool input(){
    
    string s[MAX];
    init(); 
    
    cin >> s[1];
    if(s[1] == "#")        //结束返回 false 
        return false;
    
    for(int i=2; i<MAX; i++){
        cin >> s[i];
    }
    
    for(int i=1; i<MAX; i++){
        node[i].stk.push(s[i]);
    }
    
}

int treblePre(int a){
    
    int b = a;
    
    for(int i=1; i<=3; i++){
        b = l[b];
        if(b == 0)        //若不存在 返回 0 
            return 0;    
    }
    
    return b;
    
}

void output(){
    
    int sum;
    int cnt = 0;
    
    for(int i=r[0]; i!=0; i=r[i]){
        cnt++;
    }
    
    if(cnt == 1)
        printf("1 pile remaining:");
    else
        printf("%d piles remaining:", cnt);
    
    for(int i=r[0]; i!=0; i=r[i]){
        sum = 0;
        while(!node[i].stk.empty()){
            node[i].stk.pop();
            sum++;
        }
        printf(" %d", sum);
    }
    
    printf("\n");
    
}

 

"Accordian" Patience (UVa 127) 双向链表 栈