1. 程式人生 > >Card Hand Sorting(列舉排列+最長公共子序列)

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;
}