Card Hand Sorting(枚举排列+最长公共子序列)

                                     Card Hand Sorting

                                                                 时间限制: 1 Sec  内存限制: 64 MB
                                                                              提交: 60  解决: 22
                                                                 [提交] [状态] [讨论版] [命题人:外部导入]

When dealt cards in the card game Plump it is a good idea to start by sorting the cards in hand by suit and rank. The different suits should be grouped and the ranks should be sorted within each suit. But the order of the suits does not matter and within each suit, the cards may be sorted in either ascending or descending order on rank. It is allowed for some suits to be sorted in ascending order and others in descending order.
Sorting is done by moving one card at a time from its current position to a new position in the hand, at the start, end, or in between two adjacent cards. What is the smallest number of moves required to sort a given hand of cards?

                                                          

输入

The first line of input contains an integer n (1 ≤ n ≤ 52), the number of cards in the hand. The second line contains n pairwise distinct space-separated cards, each represented by two characters. The first character of a card represents the rank and is either a digit from 2 to 9 or
one of the letters T , J , Q , K , and A representing Ten, Jack, Queen, King and Ace, respectively, given here in increasing order. The second character of a card is from the set { s , h , d , c } representing the suits spades ♠, hearts ♥, diamonds ♦, and clubs ♣.

输出

Output the minimum number of card moves required to sort the hand as described above.

样例输入

7
9d As 2s Qd 2c Jd 8h

样例输出

2

题意
给出 一个扑克牌的序列 求排成一个“有序”序列 最少的插入次数
有序是这样定义的同一个花色的 必须放在一起

同一花色中的牌 必须是 升序 或者是 降序

然后 A 是最大的 (A 是 14 不是 1)坑啊

思路

我们可以枚举一下
一共有四种花色的 就是 4!
每种升序 有 升序 和 降序 就是 2 ^ 4
4 ! * 2 ^ 4 = 384 可以接受
然后次数 怎么求呢 就是 n - LCS

因为 这不是 交换 来变得 有序 如果是交换来变得有序 就是 求逆序数
插入的话 就将这个序列 求出其 最长上升子列 这个 子列不动 其他元素 依次 插入就可以

然后讲讲 怎么枚举

首先 枚举 花色 就是
我们 将 四种花色 分别与 0 1 2 3 对应起来
然后用一个 数组 color[4]= {0, 1, 2, 3} 求这个花色的全排列 这就定义了 花色的 先后次序

color[i] 表示 数字i 对应的花色的优先级是多少

然后 枚举 升序 降序

我们可以用 0-15 这16 个数字的二进制来表示 升序 还是降序

我们可以重新 给它 定义一个 tv
降序 就是将 原值 取负数 然后 按 升序排序 实际上 就是 原值的降序排序

比如 0 这个数字 对应四位的二进制数字 是 0000

所以 这个时候 四种花色 都是 升序的 我们可以用花色的优先级 来表示 对应哪位数字

比如 此时 s 花色 对应的 优先级是 0 那么 就是将 0 右移 0 位 再 & 1 就可以判断它对应位 是 1 还是 0

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
struct node
{
    int id;
    int colr;
    int num;
    int tv;
}p[150];
int color[4]={0,1,2,3};
int n;
int cmp(node a,node b)
{
    if(a.colr==b.colr)
        return a.tv<b.tv;

    return color[a.colr]<color[b.colr];


}
char s[150];
int LCS()
{
    int dp[60];
    memset(dp,0,sizeof(dp));
    dp[0] = 1;
    int ans = 1;
    for (int i = 1; i < n; i++)
    {
        dp[i] = 1;
        for (int j = 0; j < i; j++)
        {
            if (p[i].id > p[j].id)
            {
                dp[i] = max(dp[i], dp[j] + 1);
            }
        }
        ans = max(dp[i], ans);
    }
    return ans;
}

int main()
{

    int ans=inf;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%s",s);
        if(s[0]=='T')p[i].num=10;
        else if(s[0]=='J')p[i].num=11;
        else if(s[0]=='Q')p[i].num=12;
        else if(s[0]=='K')p[i].num=13;
        else if(s[0]=='A')p[i].num=14;
        else p[i].num=s[0]-'0';

        if(s[1]=='s')p[i].colr=0;
        else if(s[1]=='h')p[i].colr=1;
        else if(s[1]=='d')p[i].colr=2;
        else if(s[1]=='c')p[i].colr=3;
        p[i].id=i;
    }
    do
    {
        for(int i=0;i<16;i++)
        {
            for(int j=0;j<n;j++)
            {
                p[j].tv=p[j].num*(((i>>color[p[j].colr])&1) ? 1 : -1);

            }
            sort(p,p+n,cmp);
            int minn=n-LCS();
            ans=min(minn,ans);
        }
    }while(next_permutation(color,color+4));
    printf("%d\n",ans);
    return 0;
}



猜你喜欢

转载自blog.csdn.net/qq_41021816/article/details/82956274
今日推荐