UVA 11421 - Arranging Cards

Problem E
Arranging Cards
Input:
Standard Input

Output: Standard Output

 

Given n (n <= 50) different cards, you're going to arrange them in a sequence so that adjacent cards always have different ranks.

 

Each card is represented by two characters: its rank (2~9,T for ten,J for Jack,Q for Queen,K for King,A for Ace) and suite (S for Spade,C for Club,H for Heart,D for Diamond). The whole sequence is represented by the concatenation of all the cards. For example, 6H7DJDKC is a valid sequence, but 6H7D7SKC is not, because there are two adjacent cards 7D and 7S with the same rank.

 

Given a positive integer k (1 ≤ k ≤ 1018), find the lexicographically k-th smallest sequence.

 

Input

The input contains at most 1000 test cases. Each case begins with two integers n and k in the first line. The second line contains n cards separated by a single space. The case with n = 0 indicates the end of the input and should not be processed.

 

Output

For each case, print the case number and the answer. If there is no such sequence, print "Not found" (without quotes). Insert a single space between each two adjacent cards to make it look better.

 

Sample Input

6 1

2S 3S 3C 4S 4C 4D

6 120

2S 3S 3C 4S 4C 4D

6 121

2S 3S 3C 4S 4C 4D

16 654321234567

2S 3S 4S 5S 2C 3C 4C 5C 2D 3D 4D 5D 2H 3H 4H 5H

0 0

 

Output for Sample Input

Case 1: 2S 4C 3C 4D 3S 4S

Case 2: 4S 3S 4D 3C 4C 2S

Case 3: Not found

Case 4: 5D 4S 2D 5H 3S 4H 5S 2H 3D 2C 5C 4D 2S 3C 4C 3H


Problemsetter: Rujia Liu

Special thanks: Dong Zhou

 


题意:有n张牌,各个牌是不一样的,即使他们有一样的rank和suit也是不一样的。 现在要将他们排成一行,并且相邻的牌的rank不一样。 求字典序是第k小的情况。


思路:算是这题的加强版.....http://www.lydsy.com/JudgeOnline/problem.php?id=1079


代码:

#include <iostream>
#include <vector>
#include <algorithm>
#include <string.h>
#include <cstring>
#include <map>
#include <set>
#include <stdio.h>
#include <cmath>
#include <cassert>
#include <math.h>
#define rep(i,a,b) for(int i=(a);i<(b);++i)
#define rrep(i,b,a) for(int i = (b); i >= (a); --i)
#define clr(a,x) memset(a,(x),sizeof(a))
#define LL unsigned long long
#define eps 1e-9
#define mp make_pair
using namespace std;

const LL maxk = 1e18;

struct State
{
    short pre;
    short a[51];
    bool operator < (const State & st) const
    {
        if (pre != st.pre) return pre < st.pre;
        rep(i,0,51)
        if (a[i] != st.a[i]) return a[i] < st.a[i];
        return false;
    }
    bool operator == (const State & st) const
    {
        if (pre != st.pre) return false;
        rep(i,0,51) if (a[i] != st.a[i]) return false;
        return true;
    }
};


const int maxn = 50+5;
int n;
long long K;

map<State,LL> dp;
int num[256],sum[maxn];

pair<char,char> card[maxn];
void input()
{
    char s[10];
    rep(i,0,n) {
        scanf("%s",s);
        card[i] = mp(s[0],s[1]);
    }
    sort(card,card+n);
}

int ans[maxn];
bool vis[maxn];

LL add(LL a,LL b)
{
    if (a >= maxk || b >= maxk
        || a + b >= maxk) return maxk;
    return a + b;
}

LL mul(LL a,LL b)
{
    if (a > b) swap(a,b);
    if (b >= maxk) return maxk;
    if (a > maxk / b) return maxk;
    return a * b;
}

LL dfs(State st)
{
    map<State,LL>::iterator it;
    it = dp.find(st);
    if (it != dp.end()) return it->second;
    LL & t = dp[st];
    int n = 0,maxi = 0;
    rep(i,0,51) {
        n += st.a[i] * i;
        if (st.a[i] > 0) maxi = i;
    }
    if (n == 0) return t = 1;
    if (maxi + maxi - 1 > n) return t = 0;
    int pre = st.pre;
    rep(i,1,51) if (st.a[i]) {
        --st.a[i];
        if (i - 1 > 0) ++st.a[i-1];
        st.pre = i;
        t = add(t,dfs(st) * (st.a[i] + 1 - (pre == i+1)));
        ++st.a[i];
        if (i - 1 > 0) --st.a[i-1];
        if (t >= maxk) break;
    }
    return t;
}

LL A[maxn];

void solve()
{
    clr(num,0); clr(sum,0);
    rep(i,0,n) {
        int x = ++num[card[i].first];
        ++sum[x]; --sum[x-1];
    }
    State start; clr(start.a,0);
    rep(i,1,n+1) {
        start.a[i] = sum[i];
        start.pre = maxn*2;
    }
    clr(vis,0);
    bool no_ans = false;
    rep(i,0,n) {
        int j = 0;
        for(; j < n; ++j) if (!vis[j]) {
            if (i > 0 && card[ans[i-1]].first == card[j].first) continue;
            int x = --num[card[j].first];
            vis[j] = true;
            if (x > 0) ++start.a[x];
            --start.a[x+1];
            start.pre = x+1;
            //++sum[x]; --sum[x+1];
            LL t = dfs(start);
            LL a = 1;
            rep(k,2,n+1) {
                rep(w,0,start.a[k]) {
                    a = mul(a,A[k]);
                    if (a >= K) break;
                }
                if (a >= K) break;
            }
            t = mul(t,a);
            if (t >= K) break;
            vis[j] = false;
            K -= t;
            if (x > 0) --start.a[x];
            ++start.a[x+1];
            ++num[card[j].first];
        }
        if (j >= n) {
            no_ans = true;
            break;
        }
        ans[i] = j;
    }
    if (no_ans || K != 1) puts("Not found");
    else {
        rep(i,0,n) {
            char x = card[ans[i]].first;
            char y = card[ans[i]].second;
            printf("%c%c",x,y);
            if (i != n-1) printf(" ");
        }
        puts("");
    }
}

int main()
{
    #ifdef ACM
        freopen("in.txt", "r", stdin);
       // freopen("out.txt","w",stdout);
    #endif // ACM
    int cas = 0;
    A[0] = 1;
    rep(i,1,maxn) A[i] = mul(A[i-1],i);
    while (scanf("%d",&n)==1) {
        scanf("%lld",&K);
        if (n == 0) break;
        input();
        ++cas;
        printf("Case %d: ",cas);
        solve();
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值