UVA 127 "Accordian" Patience


题意:有52张牌从左往右放在桌子上,一开始每张牌算一个牌堆。如果两张牌可以匹配当且仅当这两张牌的花色或者点数相同。现在每个牌堆的最上面的牌可以和它左边的第一个牌堆上的第一张牌或左边第三个牌堆上的第一张牌匹配,如果匹配成功,就把这张牌放到对应的牌堆上。如果都能匹配,优先去和左边第三个牌堆匹配。存在多个牌堆可以发生匹配的情况,优先去执行靠左的牌堆。如果一个牌堆为空,这个牌堆就不再用了,右边所有牌都向左移动一个位置。一直执行到无法匹配时,剩余每个牌堆牌的数量。

思路:用链表模拟一下过程。next[i]表示编号为i的牌堆右边牌堆的编号。last[i]表示编号为i的牌堆左边牌堆的编号。如果牌堆i的牌数变为0,那么就把i删除掉,last[i]的next应该指向next[i],next[i]的last应该指向last[i](先判断i是不是最后一个牌堆)。


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;

#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)
#define Clean(x,y) memset(x,y,sizeof(x))
int next[60],last[60];

struct node
{
    char x,y;
    node(char tx = ' ',char ty = ' ')
    {
        x = tx;
        y = ty;
    }
};

vector<node> p[60];

bool init()
{
    char tx,ty;
    tx = getchar();
    if ( tx=='#' ) return false;
    rep(i,1,52)
    {
        p[i].clear();
        if( i!=1 ) tx = getchar();
        ty = getchar();
        getchar();
        p[i].push_back( node(tx,ty) );
    }
    last[1] = 0;
    next[52] = -1;
    rep(i,1,51) next[i] = i + 1;
    rep(i,2,52) last[i] = i - 1;

    return true;
}

bool match(node a,node b)
{
    if ( a.x == b.x || a.y == b.y ) return true;
    return false;
}

void move(int x,int y) //x牌堆上的牌放到y牌堆上
{
    p[y].push_back( p[x][p[x].size()-1] );
    p[x].pop_back();
    if ( p[x].size() == 0 ) //删除x牌堆
    {
        int L = last[x];
        int R = next[x];
        next[ L ] = R;
        if ( R!=-1 ) last[R] = L;
    }
}

bool check(int x)
{
    if ( p[x].size() == 0 ) return false;
    int x1,x2;
    x1 = x;
    rep(i,1,3) x1 = last[x1];//左边第三个牌堆
    x2 = last[x]; //左边第一个牌堆
    if ( x1 != 0 && match( p[x1][ p[x1].size()-1 ]  , p[x][p[x].size()-1] ) )
    {
        move(x,x1);
    }
    else if ( x2 != 0 && match( p[x2][ p[x2].size()-1 ]  , p[x][p[x].size()-1] ) )
    {
        move(x,x2);
    }
    else return false;
    return true;
}

int main()
{
    while(init())
    {
        bool can = true;
        while(can)
        {
            can = false;
            rep(i,2,52) //第一个牌堆前面没有牌堆与其去匹配
            if ( check(i) ) {can = true; break;}
        }
        int k = 1;
        int num = 0;
        while( k!=-1 )
        {
            num++;
            k = next[k];
        }
        if ( num == 1 ) printf("%d pile remaining:",1);
        else printf("%d piles remaining:",num);
        k = 1;
        rep(i,1,num)
        {
            printf(" %d",p[k].size());
            k = next[k];
        }
        puts("");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值