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

转自:https://blog.csdn.net/qq_38786088/article/details/79793849

题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=2020

题目:
Description
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?

Input
There will be several test cases. For the each case, 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
Output the minimum number of card moves required to sort the hand as described above.

Sample Input
4
2h Th 8c Qh
7
9d As 2s Qd 2c Jd 8h
4
2h 3h 9c 8c
Sample Output
1
2
0

题意:就是一首扑克牌,没有大王和小王,最多输入52张,有顺序的输入牌,每张牌有两个属性,花色和大小,题目要求让同种花色的牌放在一起,且同种花色的牌,要满足升序或降序,不同花色之间的顺序没有要求,问至少要移动多少次牌,牌的移动不是交换两张牌的位置,而是插入到某个位置。

* 这个问题是非常繁琐的,比赛时一直都往贪心方面想!我们执着于找到一种最优排序结果,
但是其实反过来想总共才多少种结果(满足题意的最终排序), (由左到右分成4组,即4种类型排序4!,
且每组可升序或降序所以有2^4,即总方案数为4!*2^4=24*16=384种)!
** 我们仅需要寻找一种通法来求解: 原输入序列排成满足题意的序列需要调的最少牌数。
满足题意的序列为由小到大编号,原序列对应的排的值为此编号,我们要将原排序乱序排成由小到大排列,
我们仅需要找出最长上升子序列,其它不属于此序列的元素,都需要移动一次才能使其变为满足题意的序列!
** 我们已经找到了通法,仅需要遍历所有的符合题意的序列需要原序列调动最少张牌形成,找出其中最小值即为
ans!

代码:

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;

struct node_t{
    int val;
    int suit;
    int idx;
}p[60];

int increas[6],ssort[6];
bool cmp(node_t a,node_t b){
    if(a.suit==b.suit)
       return (increas[a.suit]&&a.val<b.val)||(!increas[a.suit]&&a.val>b.val);
    return ssort[a.suit]<ssort[b.suit];
}

int Idx[60],flag[6]={0};
int DP[60];
char s[3];
int ans,n;
int S_Int_val(char a){
    if('2'<=a&&a<='9')
        return a-'1';
    if(a=='T') return 9;
    if(a=='J') return 10;
    if(a=='Q') return 11;
    if(a=='K') return 12;
    return 13;
}

int S_Int_suit(char a){
    if(a=='s') return 1;
    if(a=='h') return 2;
    if(a=='d') return 3;
    return 4;
}

void dfs(int rt){
    if(rt==0){
        sort(p,p+n,cmp);
        for(int i=0;i<n;++i)
            Idx[p[i].idx]=i;

        DP[0]=1;
        int maxn=1;
        for(int i=1;i<n;++i){
            DP[i]=1;
            for(int j=0;j<i;++j)
                if(Idx[j]<Idx[i]) DP[i]=max(DP[j]+1,DP[i]);
            maxn=max(maxn,DP[i]);
        }
        ans=min(n-maxn,ans);

    }

    for(int i=1;i<=4;++i){//枚举四种花色的排序,共24种
        if(flag[i])continue;
        flag[i]=1;
        ssort[rt]=i;
        dfs(rt-1);
        flag[i]=0;
    }
}

int main(){
    while(~scanf("%d",&n)){
        for(int i=0;i<n;++i){
            scanf("%s",s);
            p[i].val=S_Int_val(s[0]);//
            p[i].suit=S_Int_suit(s[1]);
            p[i].idx=i;
        }

        ans=1e9;
        for(int i=0;i<(1<<4);++i){
            for(int j=0;j<4;++j)
                increas[j+1]=((1<<j)&i)?1:0;//枚举每一种花色的升序和降序,共16种,1为升序,0为降序。
            dfs(4);
        }
        printf("%d\n",ans);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36300700/article/details/79892828
今日推荐